package com.lamatek.tags.google;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;

import com.lamatek.tags.google.beans.TrafficEventBean;
import com.lamatek.tags.google.beans.XMLParser;
/**
 * GoogleMapTag
 * 
 * This class represents a &lt;googlemaps;map> tag. Developers should not subclass or override this
 * class or it's methods.
 * 
 * @author Tom Cole
 * @version 0.40
 */
public class GoogleMapTag extends BodyTagSupport implements Serializable, GoogleMapEventListener {
    
    static final int SMALL_ZOOM_CONTROL = 0;
    static final int LARGE_ZOOM_CONTROL = 1;
    Hashtable markers = null;
    Hashtable points = null;
    Hashtable polylines = null;
    Hashtable circles = null;
    Hashtable polygons = null;
    Hashtable boxes = null;
    Hashtable traffic_tags = null;
    Hashtable overlays = null;
    Hashtable mapTypes = null;
    Hashtable wms = null;
    Vector events = null;
    Vector labels = null;
    Vector inserts = null;
    Hashtable keys = null;
    boolean showTypeControl = false;
    boolean showZoomControl = false;
    boolean showPanControl = true;
    boolean showScaleControl = false;
    boolean mouseWheelSupport = false;
    boolean panEnabled = true;
    String version = "2";
    String id = null;
    int zoomControlSize = SMALL_ZOOM_CONTROL;
    String width = null;
    String height = null;
    String type = "map";
    int zoom = -1;
    String scope = "page";
    double centerLatitude = -181.00d;
    double centerLongitude = -181.00d;
    double smallLon = 180.00d;
    double smallLat = 180.00d;
    double largeLon = -180.00d;
    double largeLat = -180.00;
    String body = "";
    GoogleMapMessageTag message = null;
    GoogleMapOverviewTag overviewControl = null;
    GoogleMapClusterTag clusterer = null;
    GoogleMapCoordinatesTag coords = null;
    String xml = null;
    boolean debug = false;
    boolean headless = false;
    int minZoom = 0;
    int maxZoom = 17;
    boolean bound = false;
    String language = "en";
    boolean showDaylight = false;
    /**
     * Overrides doStartTag from BodyTagSupport. Developers should not override this
     * method.
     */
    public int doStartTag() {
        if (scope.equalsIgnoreCase("site")) {
            if (pageContext.getSession().getAttribute(id) == null) {
                if (xml != null) {
                    parseXML();
                }
                return EVAL_BODY_INCLUDE;
            }
        }
        else {
            if (pageContext.getAttribute(id) == null) {
                if (xml != null) {
                    parseXML();
                }
                return EVAL_BODY_INCLUDE;
            }
        }
        return SKIP_BODY;
    }
    /**
     * Parses the defined XML file (or generator), if specified, and adds the resulting entities...
     * 
     */
    private void parseXML() {
        XMLParser.parseXML(xml, this);
    }
    /**
     * Overrides doEndTag from BodyTagSupport. Developers should not override this
     * method.
     */
    public int doEndTag() {
        if (scope.equalsIgnoreCase("site")) {
            if (pageContext.getSession().getAttribute(id) == null)
                pageContext.getSession().setAttribute(id, this);
        }
        else {
            if (pageContext.getAttribute(id) == null)
            	pageContext.setAttribute(id, this);
        }
        return EVAL_PAGE;
    }
    /**
     * This method adds a GoogleMapMarkerTag to the map.
     * 
     * @param marker An initialized GoogleMapMarkerTag.
     */
    public void addMarker(GoogleMapMarkerTag marker) {
        if (markers == null)
            markers = new Hashtable();
        markers.put(marker.getId(), marker);
    }
    /**
     * Removes a previously added GoogleMapMarkerTag from this map.
     * 
     * @param marker The GoogleMapMarkerTag to remove.
     */
    public void removeMarker(GoogleMapMarkerTag marker) {
        if (markers != null && marker != null) {
            markers.remove(marker.getId());
        }
    }
    /**
     * Retrieves a GoogleMapMarkerTag by it's id.
     * 
     * @param name The id of the GoogleMapMarkerTag to retrieve.
     * @return The GoogleMapMarkerTag with this id, or null.
     */
    public GoogleMapMarkerTag getMarker(String name) {
        if (markers != null) {
            return (GoogleMapMarkerTag) markers.get(name);
        }
        else {
            return null;
        }
    }
    /**
     * Adds a map type to the map storing it by id.
     * 
     * @param mapType An initialized GoogleMapMapTypeTag
     */
    public void addMapType(GoogleMapMapTypeTag mapType) {
        if (mapTypes == null)
            mapTypes = new Hashtable();
        mapTypes.put(mapType.getId(), mapType);
    }
    /**
     * Returns the GoogleMapMapTypeTag with the given id
     * or null if it cannot be found.
     * 
     * @return A GoogleMapMapTypeTag with the given id or null.
     */
    public GoogleMapMapTypeTag getMapType(String id) {
        if (mapTypes == null)
            return null;
        else
            return (GoogleMapMapTypeTag) mapTypes.get(id);
    }
    /**
     * Removes the map type with the given id.
     * 
     * @param id The id of the map type to remove.
     */
    public void removeMapType(String id) {
        if (mapTypes != null)
            mapTypes.remove(id);
    }
    /**
     * Retrieves a GoogleMapBoxtag by it's id.
     * 
     * @param name The id of the GoogleMapBoxTag to retrieve.
     * @return A GoogleMapBoxTag with the given id or null.
     */
    public GoogleMapBoxTag getBox(String name) {
        if (boxes != null)
            return (GoogleMapBoxTag) boxes.get(name);
        else
            return null;
    }
    /**
     * Retrieves a GoogleMapCircletag by it's id.
     * 
     * @param name The id of the GoogleMapCircleTag to retrieve.
     * @return A GoogleMapCircleTag with the given id or null.
     */
    public GoogleMapCircleTag getCircle(String name) {
        if (circles != null)
            return (GoogleMapCircleTag) circles.get(name);
        else
            return null;
    }
    /**
     * Retrieves a GoogleMapImageOverlayTag by it's id.
     * 
     * @param name the id of the GoogleMapImageOvelay to retrieve.
     * @return A GoogleMapImageOverlayTag with the given id, or null.
     */
    public GoogleMapImageOverlayTag getImageOverlay(String name) {
        if (overlays == null)
            return null;
        else 
            return (GoogleMapImageOverlayTag) overlays.get(name);
    }
    /**
     * Retrieves a GoogleMapPolygonTag by it's id.
     * 
     * @param name The id of the GoogleMapPolygonTag to retrieve.
     * @return A GoogleMapPolygonTag with the given id or null.
     */
    public GoogleMapPolygonTag getPolygon(String name) {
        if (polygons != null)
            return (GoogleMapPolygonTag) polygons.get(name);
        else
            return null;
    }
    /**
     * Retrieves a GoogleMapPolylineTag by it's id.
     * 
     * @param name The id of the GoogleMapPolylineTag to retrieve.
     * @return A GoogleMapPolylineTag with the given id or null.
     */
    public GoogleMapPolylineTag getPolyline(String name) {
        if (polylines != null)
            return (GoogleMapPolylineTag) polylines.get(name);
        else
            return null;
    }
    /**
     * Adds a new GoogleMapPointTag to this map. GoogleMapPointTags are used
     * as location references for all overlays (markers, circles, boxes,
     * polygons and polylines) in a map.
     * 
     * @param point The initialized GoogleMapPointTag to add.
     */
    public void addPoint(GoogleMapPointTag point) {
        if (points == null)
            points = new Hashtable();
        points.put(point.getId(), point);
        if (point.getLatitude() < smallLat)
            smallLat = point.getLatitude();
        if (point.getLatitude() > largeLat)
            largeLat = point.getLatitude();
        if (point.getLongitude() < smallLon)
            smallLon = point.getLongitude();
        if (point.getLongitude() > largeLon)
            largeLon = point.getLongitude();
    }
    /**
     * Adds a new GoogleMapCircleTag to this map.
     * 
     * @param circle The initialized GoogleMapCircleTag to add.
     */
    public void addCircle(GoogleMapCircleTag circle) {
        if (circles == null) 
            circles = new Hashtable();
        circles.put(circle.getId(), circle);
    }
    /**
     * Adds a new image overlay to this map.
     * 
     * @param image The initialized GoogleMapImageOverlayTag to add.
     */
    public void addImageOverlay(GoogleMapImageOverlayTag image) {
        if (overlays == null)
            overlays = new Hashtable();
        overlays.put(image.getId(), image);
    }
    /**
     * Adds a new GoogleMapTrafficTag to this map.
     * 
     * @param traffic_tag The initialized GoogleMapTrafficTag to add.
     */
    public void addTraffic_tag(GoogleMapTrafficTag traffic) {
        if (traffic_tags == null) 
            traffic_tags = new Hashtable();
        traffic_tags.put(traffic.getId(), traffic);
    }
    /**
     * Adds a new GoogleMapPolygonTag to this map.
     * 
     * @param polygon The initialized GoogleMapPolygonTag to add.
     */
    public void addPolygon(GoogleMapPolygonTag polygon) {
        if (polygons == null) {
            polygons = new Hashtable();
        }
        polygons.put(polygon.getId(), polygon);
    }
    /**
     * Adds a new GoogleMapPolylineTag to this map.
     * 
     * @param polyline The initialized GoogleMapPolylineTag to add.
     */
    public void addPolyline(GoogleMapPolylineTag polyline) {
        if (polylines == null)
            polylines = new Hashtable();
        polylines.put(polyline.getId(), polyline);
    }
    /**
     * Adds a new GoogleMapBoxTag to this map.
     * 
     * @param box The initialized GoogleMapBoxTag to add.
     */
    public void addBox(GoogleMapBoxTag box) {
        if (boxes == null)
            boxes = new Hashtable();
        boxes.put(box.getId(), box);
    }
    /**
     * Adds a new GoogleMapEventTag to this map.
     * 
     * @param event The initialized GoogleMapEventTag to add.
     */
    public void addEvent(GoogleMapEventTag event) {
        if (events == null)
            events = new Vector();
        events.add(event);
    }
    /**
     * Adds a new GoogleMapKeyTag to this map.
     * 
     * @param key The initialized GoogleMapKeyTag to add.
     */
    public void addKey(GoogleMapKeyTag key) {
        if (keys == null)
            keys = new Hashtable();
        keys.put(key.domain, key.key);
    }
    /**
     * Sets the singleton GoogleMapPanControlTag used by this map.
     * 
     * @param control The initialized GoogleMapPanControlTag to add.
     */
    public void setPanControl(GoogleMapPanControlTag control) {
        showPanControl = control.isEnable();
        panEnabled = control.isEnable();
    }
    /**
     * Sets the singleton GoogleMapWheelControlTag used by this map.
     * 
     * @param control The initialized GoogleMapWheelControlTag to add.
     */
    public void setWheelControl(GoogleMapWheelControlTag control) {
        mouseWheelSupport = control.isEnable();
    }
    /**
     * Sets the singleton GoogleMapTypeControlTag used by this map.
     * 
     * @param control The initialized GoogleMapTypeControlTag to add.
     */
    public void setTypeControl(GoogleMapTypeControlTag control) {
        showTypeControl = control.isEnable();
    }
    /**
     * Sets the singleton GoogleMapScaleControlTag used by this map.
     * 
     * @param control The initialized GoogleMapScaleControlTag to add.
     */
    public void setScaleControl(GoogleMapScaleControlTag control) {
        showScaleControl = control.isEnable();
    }
    /**
     * Sets the singleton GoogleMapZoomControlTag used by this map.
     * 
     * @param control The initialized GoogleMapZoomControlTag to add.
     */
    public void setZoomControl(GoogleMapZoomControlTag control) {
        if (control.getSize().equalsIgnoreCase("small")) {
            zoomControlSize = SMALL_ZOOM_CONTROL;
        }
        else if (control.getSize().equalsIgnoreCase("large")) {
            zoomControlSize = LARGE_ZOOM_CONTROL;
        }
        showZoomControl = control.isEnable();
    }   
    /**
     * Sets the width of this map in pixels.
     * 
     * @param height The heigt of this map in pixels.
     */
    public void setHeight(String height) {
        this.height = height;
    }
    /**
     * Sets the id for this map. The id is used by the output
     * tags (script, javascript, div and initialize tags) to locate
     * this map.
     * 
     * @param id The id for this map.
     */
    public void setId(String id) {
        this.id = id;
    }
    /**
     * Sets the map type (map | satellite | hybrid) to display.
     * 
     * @param type The map type to display (map | satellite | hybrid).
     */
    public void setType(String type) {
        this.type = type;
    }
    /**
     * Sets the Google Maps API version to use. If set to a whole number (1 or 2)
     * the currently available stable version is used. If set to a specific
     * version (like 2.39) then that version will be attempted to load.
     * 
     * @param version The API version to load.
     */
    public void setVersion(String version) {
        this.version = version;
    }
    /**
     * Sets the width of this map in pixels.
     * 
     * @param width The width of the map in pixels.
     */
    public void setWidth(String width) {
        this.width = width;
    }
    /**
     * Sets whether or not to generate the javascript needed to 
     * support mousewheel zoom control. This option currently
     * only works when using version 1.x APIs. This is set automatically
     * when the setWheelControl method is called.
     * 
     * @param mouseWheelSupport Set to true (to enable) or false (to disable) mousewheel zoom support.
     */
    public void setMouseWheelSupport(boolean mouseWheelSupport) {
        this.mouseWheelSupport = mouseWheelSupport;
    }
    /**
     * Sets whether or not to generate the javascript needed to 
     * show the pan control. This is set automcatically when the
     * setPanControl method is called.
     * 
     * @param showPanControl Set to true (to enable) or false (to disable) pan controls.
     */
    public void setShowPanControl(boolean showPanControl) {
        this.showPanControl = showPanControl;
    }
    /**
     * Sets whether or not to generate the javascript needed to 
     * show the type control. This is set automcatically when the
     * setTypeControl method is called.
     * 
     * @param showTypeControl Set to true (to enable) or false (to disable) type controls.
     */
    public void setShowTypeControl(boolean showTypeControl) {
        this.showTypeControl = showTypeControl;
    }
    /**
     * Sets whether or not to generate the javascript needed to 
     * show the zoom control. This is set automcatically when the
     * setZoomControl method is called.
     * 
     * @param showZoomControl Set to true (to enable) or false (to disable) zoom controls.
     */
    public void setShowZoomControl(boolean showZoomControl) {
        this.showZoomControl = showZoomControl;
    }
    /**
     * Set the zoom level of the map.
     * 
     * @param zoom The zoom level of the map.
     */
    public void setZoom(int zoom) {
        this.zoom = zoom;
    }
    /**
     * Sets the scope of the map. If set to "site" then the map
     * is stored in the session. If set to "page" then the map
     * is stored in the pageContext.
     * 
     * @param scope The scope where to store the map data.
     */
    public void setScope(String scope) {
        this.scope = scope;
    }
    /**
     * Sets the body content of the map. This can be used by advanced developers
     * to add javascript controls to the map. Nearly all implementations will
     * not have a body. This should only be used by advanced javascript developers.
     * 
     * @param body The body content for this map.
     */
    public void setBody(String body) {
        this.body = body;
    }
    /**
     * Sets the latitude of the map's centerpoint. This is typically calculated
     * automatically through the points added to the map.
     * 
     * @param latitude The latitude (in decimal form) to use as the centerpoint for the map.
     */
    public void setCenterLatitude(double latitude) {
        this.centerLatitude = latitude;
    }
    /**
     * Sets the longitude of the map's centerpoint. This is typically calculated
     * automatically through the points added to the map.
     * 
     * @param longitude The longitude (in decimal form) to use as the centerpoint for the map.
     */
    public void setCenterLongitude(double longitude) {
        this.centerLongitude = longitude;
    }
    /**
     * Generates the &lt;div> tag that represents the actual map. 
     * 
     * This method is called by GoogleMapDivTag (&lt;googlemaps:div>).
     * 
     * @param div The GoogleMapDivTag that renders the output.
     */
    public void generateDivTag(GoogleMapDivTag div) {
        try {
            JspWriter out = pageContext.getOut();
            String w_unit = "px";
            String h_unit = "px";
            if (width != null && (width.indexOf("%") > 0 || width.indexOf("px") > 0))
                w_unit = "";
            if (height != null && (height.indexOf("%") > 0 || height.indexOf("px") > 0))
                h_unit = "";
            out.print("<div id=\"" + id + "\"");
            if (div.getStyle() != null) {
                out.print(" style=\"");
                if (width != null) {
                    out.print("width: " + width + w_unit + ";");
                }
                if (height != null) {
                    out.print("height: " + height + h_unit + ";");
                }
                out.print(div.getStyle() + "\"");
            }
            else {
                out.print(" style=\"width: " + width + w_unit + "; height: " + height + h_unit + ";\"");
            }
            if (div.getCss_class() != null) {
                out.print(" class=\"" + div.getCss_class() + "\"");
            }
            out.print(">");
            out.print(body);
            out.println("</div>");
            if (message != null) {
                out.print("<div id=\"message_div\" ");
                if (message.getStyle() != null) {
                    out.print(" style=\"" + message.getStyle() + "; visibility: hidden;\">");
                }
                else {
                    out.print(" style=\"border: 1px dotted #660000; background-color: #ffffff; color: #000000; opacity: .75; filter: alpha(opacity=75); visibility: hidden;\">");
                }
                out.println("</div>");
            }
            if (overlays != null) {
                Enumeration names = overlays.keys();
                while (names.hasMoreElements()) {
                    GoogleMapImageOverlayTag image = (GoogleMapImageOverlayTag) overlays.get(names.nextElement());
                    out.print("<div id=\"" + image.getId() + "\" style=\"opacity: " + image.getOpacity() + "; filter: alhpa(opacity=" + (image.getOpacity() * 100) + "); visibility: hidden;\">");
                    if (image.getLink() != null) {
                        out.print("<a href=\"" + image.getLink() + "\">");
                    }
                    out.print("<img src=\"" + image.getUrl() + "\" border=\"0\"/>");
                    if (image.getLink() != null) {
                        out.print("</a>");
                    }
                    out.println("</div>");
                }
            }
            if (coords != null) {
                out.print("<div id=\"_coords\"");
                if (coords.getStyle() != null)
                    out.print(" style=\"" + coords.getStyle() + "; visibility: hidden;\"");
                else
                    out.print(" style=\"visibility: hidden;\"");
                if (coords.getCss_class() != null)
                    out.print(" class=\"" + coords.getCss_class() + "\"");
                out.println("></div>");
            }
        }
        catch(Exception ex) {
            ex.printStackTrace(System.err);
        }
    }
    /**
     * Generates the &lt;script> tag that imports the Google Maps API code.
     * Developers should not override this method.
     */
    public void generateScriptTag() {
        try {
            JspWriter out = pageContext.getOut();
            String domain = pageContext.getRequest().getServerName();
            if (keys != null) {
	            String key = (String) keys.get(domain); 
	            //added second key check for ids with ports and subdirectories
	            if (key == null) {
	            	Enumeration domains = keys.keys();
	            	while (domains.hasMoreElements()) {
	            		String domainName = (String) domains.nextElement();
	            		if (domainName.indexOf(domain) >= 0)
	            			key = (String) keys.get(domainName);
	            	}
	            }
	            //end add.
	            if (key == null) {
	                System.err.println("ERROR: Unable to locate GoogleMaps API key for domain " + domain);
	            }
	            else {
	                out.println("<script src=\"http://maps.google.com/maps?file=api&v=" + version + "&key=" + key + "&hl=" + language + "\" type=\"text/javascript\"></script>");
	                if (clusterer != null) {
	                    out.println("<script src=\"" + clusterer.getPathToScript() + "\" type=\"text/javascript\"></script>");
	                }
	                if (wms != null) {
	                    GoogleMapWMSTag tag = (GoogleMapWMSTag) wms.elements().nextElement();
	                    out.println("<script src=\"" + tag.getPathToScript() + "\" type=\"text/javascript\"></script>");
	                }
	                if (showDaylight) {
	                	out.println("<script src=\"http://www.daylightmap.com/daylight.js\" type=\"text/javascript\"></script>");
	                }
	            }
            }
            else {
                System.err.println("ERROR: No GoogleMap API keys were registered.");
            }
        }
        catch(Exception ex) {
            ex.printStackTrace(System.err);
        }
    }
    /**
     * Generates the javascript code that initializes the map. Developers
     * should not override this method.
     */
    public void generateInitializationCode() {
        try {
            JspWriter out = pageContext.getOut();
            out.println("<script type=\"text/javascript\">");
            out.println("//<![CDATA[");
            out.println("initializeMap" + id + "();");
            if (mouseWheelSupport) {
                if (version.indexOf("1") == 0) {
                    out.println("hookMouseWheelHandlers(\"" + id + "\")");
                }
                else if (version.indexOf("2") == 0) {
                    //future version 2 support...
                }
            }
            out.println("//]]>");
            out.println("</script>");
        }
        catch(Exception ex) {
            ex.printStackTrace(System.err);
        }
    }
    /**
     * Generates the complex javascript/AJAX code the map needs to function.
     * Developers should not override this method.
     */
    public void generateJavascript() {
        try {
            JspWriter out = pageContext.getOut();
            //Let's get the IE Polyline thing resolved...
            out.println("<style type=\"text/css\">");
            out.println("\tv\\:* {");
            out.println("\t\tbehavior:url(#default#VML);");
            out.println("\t}");
            out.println("</style>");
            //Gettin' jiggy with it!
            out.println("<script type=\"text/javascript\">");
            out.println("//<![CDATA[");
            out.println("var " + id + ";");
            out.println("var lastCenterLat;");
            out.println("var lastCenterLon;");
            out.println("var lastClick = new Date();");
            if (inserts != null && version.indexOf("2") == 0) {
                for (int i = 0; i < inserts.size(); i++) {
                    out.println("var " + ((GoogleMapInsertTag) inserts.elementAt(i)).getId() + ";");
                }
            }
            out.println("if(document.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#SVG\",\"1.1\")) {");
            out.println("\t_mSvgEnabled = true;");
            out.println("\t_mSvgForced = true;");
            out.println("}");
            out.println("function isDouble() {");
            out.println("\tvar now = new Date();");
            out.println("\tvar double_click = ((now.getTime() - lastClick.getTime()) < 500);");
            out.println("\tlastClick = now;");
            out.println("\treturn double_click;");
            out.println("}");
            if (message != null) {
                out.println("function showMessage() {");
                if (debug && version.indexOf("2") == 0) {
                    out.println("\tGLog.write('Displaying message panel.');");
                }
                out.println("\tvar message_div = document.getElementById(\"message_div\");");
                out.println("\tvar google_map = document.getElementById(\"" + id + "\");");
                out.println("\tif (message_div != null && google_map != null) {");
                out.println("\t\tmessage_div.innerHTML = \"" + message.getMessage() + "\";");
                out.println("\t\tgoogle_map.appendChild(message_div);");
                out.println("\t\tmessage_div.style.zIndex = parseInt(google_map.style.zIndex + 1);");
                out.println("\t\tmessage_div.style.position = 'absolute';");
                out.println("\t\tmessage_div.style.top = ((google_map.offsetHeight - message_div.offsetHeight) / 2) + \"px\";");
                out.println("\t\tmessage_div.style.left = ((google_map.offsetWidth - message_div.offsetWidth) / 2) + \"px\";");
                out.println("\t\tmessage_div.style.visibility = 'visible';");
                out.println("\t}");
                out.println("}");
                out.println("function hideMessage() {");
                if (debug && version.indexOf("2") == 0) {
                    out.println("\tGLog.write('Hiding message panel.');");
                }
                out.println("\tvar message_div = document.getElementById(\"message_div\");");
                out.println("\tif (message_div != null) {");
                out.println("\t\tmessage_div.style.zIndex = 0;");
                out.println("\t\tmessage_div.style.visibility = 'hidden';");
                out.println("\t}");
                out.println("}");
            }
            if (overlays != null) {
                out.println("function showImageOverlay(image_id, x, y) {");
                out.println("\tvar image_div = document.getElementById(image_id);");
                out.println("\tvar google_map = document.getElementById(\"" + id + "\");");
                out.println("\t\tgoogle_map.appendChild(image_div);");
                out.println("\timage_div.style.zIndex = 100;");
                out.println("\timage_div.style.position = 'absolute';");
                out.println("\timage_div.style.top = y + \"px\";");
                out.println("\timage_div.style.left = x + \"px\";");
                out.println("\timage_div.style.visibility = 'visible';");
                out.println("}");
            }
            if (coords != null && version.indexOf("2") == 0) {
                out.println("function showCoordinates(x, y) {");
                out.println("\tvar coords = document.getElementById(\"_coords\");");
                out.println("\tvar google_map = document.getElementById(\"" + id + "\");");
                out.println("\tgoogle_map.appendChild(coords);");
                out.println("\tcoords.style.zIndex = 100;");
                out.println("\tcoords.style.position = 'absolute';");
                out.println("\tcoords.style.top = y + \"px\";");
                out.println("\tcoords.style.left = x + \"px\";");
                out.println("\tcoords.style.visibility = 'visible';");
                out.println("}");
                out.println("function updateCoordinates(lon, lat) {");
                out.println("\tvar coords = document.getElementById(\"_coords\");");
                out.println("\tcoords.innerHTML = \"Lon: \" + lon + \"&deg;W Lat: \" + lat + \"&deg;N\";");
                out.println("}");
            }
            if (mapTypes != null) {
                if (version.indexOf("1") == 0) {
	                out.println("function copyObject(original) {");
	                out.println("\tvar object = new Object();");
	                out.println("\tfor (var e in original) {");
	                out.println("\t\tobject[e] = original[e];");
	                out.println("\t}");
	                out.println("\treturn object;");
	                out.println("}");
                }
            }
            if (labels != null) {
                if (version.indexOf("2") == 0) {
                    out.println("function Label(point, content, opacity, css_class, xOffset, yOffset) {");
                    out.println("\tthis.point = point;");
                    out.println("\tthis.content = content || \"\";");
                    out.println("\tthis.css_class = css_class || \"\";");
                    out.println("\tthis.opacity = opacity || 0.50;");
                    out.println("\tthis.xOffset = xOffset || 0;");
                    out.println("\tthis.yOffset = yOffset || 0;");
                    out.println("}");
                    out.println("Label.prototype = new GOverlay();");
                    out.println("Label.prototype.initialize = function (googleMap) {");
                    out.println("\tvar div = document.createElement(\"div\");");
                    out.println("\tdiv.style.position = \"absolute\";");
                    out.println("\tdiv.innerHTML = '<div class=\"' + this.css_class + '\">' + this.content + '</div>';");
                    out.println("\tgoogleMap.getPane(G_MAP_FLOAT_SHADOW_PANE).appendChild(div);");
                    out.println("\tthis.map_ = googleMap;");
                    out.println("\tthis.div_ = div;");
                    out.println("\tif(typeof(div.style.filter)=='string'){div.style.filter='alpha(opacity:'+(this.opacity*100)+')';}");
                    out.println("\tif(typeof(div.style.KHTMLOpacity)=='string'){div.style.KHTMLOpacity=this.opacity;}");
                    out.println("\tif(typeof(div.style.MozOpacity)=='string'){div.style.MozOpacity=this.opacity;}");
                    out.println("\tif(typeof(div.style.opacity)=='string'){div.style.opacity=this.opacity;}");
                    out.println("}");
                    out.println("Label.prototype.remove = function() {");
                    out.println("\tthis.div_.parentNode.removeChild(this.div_);");
                    out.println("}");
                    out.println("Label.prototype.copy = function() {");
                    out.println("\treturn new Label(this.point, this.content, this.css_class, this.opacity);");
                    out.println("}");
                    out.println("Label.prototype.redraw = function(force) {");
                    out.println("\tvar p = this.map_.fromLatLngToDivPixel(this.point);");
                    out.println("\tvar h = parseInt(this.div_.clientHeight);");
                    out.println("\tthis.div_.style.left = (p.x + this.xOffset) + \"px\";");
                    out.println("\tthis.div_.style.top = ((p.y + this.yOffset) - h) + \"px\";");
                    out.println("}");
                }
            }
            if (inserts != null) {
                if (version.indexOf("2") == 0) {
                    out.println("function Insert(point, image, size, basezoom) {");
                    out.println("\tthis.point = point;");
                    out.println("\tthis.image = image;");
                    out.println("\tthis.size = size;");
                    out.println("\tthis.basezoom = basezoom;");
                    out.println("\tvar agent = navigator.userAgent.toLowerCase();");
                    out.println("}");
                    out.println("Insert.prototype = new GOverlay();");
                    out.println("Insert.prototype.initialize = function(map) {");
                    out.println("\tvar div = document.createElement(\"div\");");
                    out.println("\tdiv.style.position = \"absolute\";");
                    out.println("\tmap.getPane(G_MAP_MAP_PANE).appendChild(div);");
                    out.println("\tthis.map_ = map;");
                    out.println("\tthis.div_ = div;");
                    out.println("}");
                    out.println("Insert.prototype.remove = function() {");
                    out.println("\tthis.div_.parentNode.removeChild(this.div_);");
                    out.println("}");
                    out.println("Insert.prototype.copy = function() {");
                    out.println("\treturn new Insert(this.point, this.image, this.size, this.basezoom);");
                    out.println("}");
                    out.println("Insert.prototype.redraw = function(force) {");
                    out.println("\tif (force) {");
                    out.println("\t\tvar p = this.map_.fromLatLngToDivPixel(this.point);");
                    out.println("\t\tvar z = this.map_.getZoom();");
                    out.println("\t\tvar scale = 1;");
                    out.println("\t\tif (z > this.basezoom) {");
                    out.println("\t\t\tscale = Math.pow(2, (z - this.basezoom));");
                    out.println("\t\t}");
                    out.println("\t\telse if (this.basezoom > z) {");
                    out.println("\t\t\tscale = 1 / Math.pow(2, (this.basezoom - z));");
                    out.println("\t\t}");
                    out.println("\t\tvar h=this.size.height * scale;");
                    out.println("\t\tvar w=this.size.width * scale;");
                    out.println("\t\tthis.div_.style.left = (p.x - w/2) + \"px\";");
                    out.println("\t\tthis.div_.style.top = (p.y - h/2) + \"px\";");
                    out.println("\t\tthis.div_.innerHTML = '<img src=\"' +this.image+ '\"  width='+w+' height='+h+' >';");
                    out.println("\t\tthis.div_.style.zIndex = -1;");
                    out.println("\t}");
                    out.println("}");
                    out.println("Insert.prototype.show = function() {");
                    out.println("\tthis.div_.style.display=\"\";");
                    out.println("}");
                    out.println("Insert.prototype.hide = function() {");
                    out.println("\tthis.div_.style.display=\"none\";");
                    out.println("}");
                }
            }
            if (overviewControl != null && overviewControl.wasPlaced() && (version.compareTo("2.41") >= 0 || version.equals("2"))) {
                out.println("function positionOverview(x,y) {");
                if (debug && version.indexOf("2") == 0) {
                    out.println("\tGLog.write('Positioning overview control.');");
                }
                out.println("\tvar overview = document.getElementById(\"" + id + "_overview\");");
                out.println("\tvar google_map = document.getElementById(\"" + id + "\");");
                out.println("\ttry {");
                out.println("\t\toverview.style.left = (x) + \"px\";");
                out.println("\t\toverview.style.top = (y) + \"px\";");
                out.println("\t\toverview.style.position = 'absolute';");  
                out.println("\t}");
                out.println("\tcatch (e) {");
                out.println("\t\talert(e);");
                out.println("\t}");
                out.println("}");
            }
            if (version.indexOf("2") == 0) {
                out.println("function setZoomLevels() {");
                out.println("\tvar mapTypes = " + id + ".getMapTypes();");
                out.println("\tfor (var i = 0; i < mapTypes.length; i++) {");
                out.println("\t\tmapTypes[i].getMinimumResolution = function() {");
                out.println("\t\t\treturn " + minZoom + ";");
                out.println("\t\t}");
                out.println("\t\tmapTypes[i].getMaximumResolution = function() {");
                out.println("\t\t\treturn " + maxZoom + ";");
                out.println("\t\t}");
                out.println("\t}");
                out.println("}");
                if (bound) {
                    out.println("var allowedBounds;");
                    out.println("function checkBounds() {");
                    out.println("\tif (allowedBounds.contains(" + id + ".getCenter())) {");
                    out.println("\t\treturn;");
                    out.println("\t}");
                    out.println("\telse {");
                    out.println("\t\tvar C = " + id + ".getCenter();");
                    out.println("\t\tvar X = C.lng();");
                    out.println("\t\tvar Y = C.lat();");
                    out.println("\t\tvar AmaxX = allowedBounds.getNorthEast().lng();");
                    out.println("\t\tvar AmaxY = allowedBounds.getNorthEast().lat();");
                    out.println("\t\tvar AminX = allowedBounds.getSouthWest().lng();");
                    out.println("\t\tvar AminY = allowedBounds.getSouthWest().lat();");
                    out.println("\t\tif (X < AminX) {X = AminX;}");
                    out.println("\t\tif (X > AmaxX) {X = AmaxX;}");
                    out.println("\t\tif (Y < AminY) {Y = AminY;}");
                    out.println("\t\tif (Y > AmaxY) {Y = AmaxY;}");
                    out.println("\t\t" + id + ".setCenter(new GLatLng(Y,X));");
                    out.println("\t}");
                    out.println("}");
                }
            }
            out.println("function initializeMap" + id + "() {");
            out.println("\tif (GBrowserIsCompatible()) {");
            if (debug && version.indexOf("2") == 0) {
                out.println("\t\tGLog.write('Initializing GMap with id " + id + ".');");
            }
            out.println("\t\t" + id + " = new GMap(document.getElementById(\"" + id + "\"));");
            if (message != null) {
                out.println("\t\tshowMessage();");
            }
            if (showDaylight) {
            	if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Initializing daylight map for map " + id + "');");
                }
            	out.println("\t\tvar daylight = new daylightLayer();");
            	out.println("\t\tdaylight.addToMap(" + id + ");");
            }
            if (debug && version.indexOf("2") == 0) {
                out.println("\t\tGLog.write('Setting initial map type to " + type + " for map " + id + "');");
            }
            // IFs below updated by Luiza Udroiu
            if (type.equalsIgnoreCase("hybrid")) {
                out.println("\t\t" + id + ".setMapType(G_HYBRID_MAP);");
            }
            else if (type.equalsIgnoreCase("satellite")) {
                out.println("\t\t" + id + ".setMapType(G_SATELLITE_MAP);");
            }
            else {
                out.println("\t\t" + id + ".setMapType(G_NORMAL_MAP);");
            }
            if (clusterer != null) {
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Initializing clusterer " + id + "_cluster.');");
                }
                out.println("\t\tvar " + id + "_cluster = new Clusterer(" + id + ", " + debug + ");");
                if (clusterer.getIcon() != null) {
                    GoogleMapIconTag icon = clusterer.getIcon();
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Creating custom clusterer icons.');");
                    }
                    out.println("\t\tvar " + id + "_cluster_icon = new GIcon();");
                    out.println("\t\t" + id + "_cluster_icon.image = '" + icon.getIcon() + "';");
                    out.println("\t\t" + id + "_cluster_icon.iconSize = new GSize(" + icon.getIconWidth() + ", " + icon.getIconHeight() + ");");
                    out.println("\t\t" + id + "_cluster_icon.iconAnchor = new GPoint(" + icon.getAnchorX() + ", " + icon.getAnchorY() + ");");
                    out.println("\t\t" + id + "_cluster_icon.infoWindowAnchor = new GPoint(" + icon.getInfoWindowAnchorX() + ", " + icon.getInfoWindowAnchorY() + ");");
                    if (icon.getShadow() != null) {
                        out.println("\t\t" + id + "_cluster_icon.shadow = '" + icon.getShadow() + "';");
                        out.println("\t\t" + id + "_cluster_icon.shadowSize = new GSize(" + icon.getShadowWidth() + ", " + icon.getShadowHeight() + ");");
                    }
                    out.println("\t\t" + id + "_cluster.SetIcon(" + id + "_cluster_icon);");
                }
                out.println("\t\t" + id + "_cluster.maxVisibleMarkers = " + clusterer.getMaxVisibleMarkers() + ";");
                out.println("\t\t" + id + "_cluster.minMarkersPerCluster = " + clusterer.getMarkersPerCluster() + ";");
                out.println("\t\t" + id + "_cluster.gridSize = " + clusterer.getGridSize() + ";");
            }
            if (wms != null && version.indexOf("1") == 0) {
                Enumeration names = wms.keys();
                while (names.hasMoreElements()) {
                    GoogleMapWMSTag tag = (GoogleMapWMSTag) wms.get(names.nextElement());
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding wms map " + tag.getId() + "');");
                    }
                    out.println("\t\tvar " + tag.getId() + " = new WMSSpec(" + id + ", '" + tag.getUrl() + "', '" + tag.getName() + "', '" + tag.getName() + "', '" + tag.getLayers() + "', '" + tag.getSrs() + "', '" + tag.getVersion() + "', 'default', '" + tag.getFormat() + "', '" + tag.getCopyright() + "');");
                    if (tag.isShowOverlay()) {
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\tGLog.write('Setting overlay for wms map " + tag.getId() + "');");
                        }
                        out.println("\t\t" + tag.getId() + ".OverlaySpec = " + id + ".mapTypes[2];");
                    }
                    out.println("\t\t" + id + ".mapTypes[" + id + ".mapTypes.length] = " + tag.getId() + ";");
                    if (tag.isShowOnStartup()) {
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\tGLog.write('Setting Google Map to initially display wms map " + tag.getId() + "');");
                        }
                        out.println("\t\t" + id + ".setMapType(" + id + ".mapTypes[" + id + ".mapTypes.length-1]);");
                    }
                }
            }
            else if (wms != null && version.indexOf("2") == 0) {
                Enumeration names = wms.keys();
                while (names.hasMoreElements()) {
                    GoogleMapWMSTag tag = (GoogleMapWMSTag) wms.get(names.nextElement());
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding wms map " + tag.getId() + "');");
                    }
                    out.println("\t\tvar " + tag.getId() + " = new WMSSpec(" + id + ", '" + tag.getUrl() + "', '" + tag.getName() + "', '" + tag.getName() + "', '" + tag.getLayers() + "', '" + tag.getSrs() + "', '" + tag.getVersion() + "', 'default', '" + tag.getFormat() + "', '" + tag.getCopyright() + "');");
                    /*
                    if (tag.isShowOverlay()) {
                        out.println("\t\tvar layer_" + tag.getId() + " = [G_SATELLITE_MAP.getTileLayers()[0], G_HYBRID_MAP.getTileLayers()[1], " + tag.getId() + "];");
                    }
                    else {
                    */
                        out.println("\t\tvar layer_" + tag.getId() + " = [" + tag.getId() + "];");
                    /*
                    }
                    */
                    out.println("\t\tvar map_" + tag.getId() + " = new GMapType(layer_" + tag.getId() + ", G_SATELLITE_MAP.getProjection(), \"" + tag.getName() + "\", G_SATELLITE_MAP);");
                    out.println("\t\t" + id + ".addMapType(map_" + tag.getId() + ");");
                    if (tag.isShowOnStartup()) {
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\tGLog.write('Setting Google Map to initially display wms map " + tag.getId() + "');");
                        }
                        out.println("\t\t" + id + ".setMapType(map_" + tag.getId() + ");");
                    }
                }
            }
            if (mapTypes != null) {
                if (version.indexOf("1") == 0) {
	                Enumeration names = mapTypes.keys();
	                while (names.hasMoreElements()) {
	                    GoogleMapMapTypeTag type = (GoogleMapMapTypeTag) mapTypes.get(names.nextElement());
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\tGLog.write('Adding custom map " + type.getId() + "');");
                        }
	                    int parentType = 0;
	                    if (type.getBaseType().equals("satellite"))
	                        parentType = 1;
	                    else if (type.getBaseType().equals("hybrid"))
	                        parentType = 2;
	                    if (debug && version.indexOf("2") == 0) {
                            out.println("\t\tGLog.write('Copying base map type " + parentType + " into map " + type.getId() + "');");
                        }
	                    out.println("\t\tvar " + type.getId() + " = copyObject(" + id + ".mapTypes[" + parentType + "]);");
	                    if (type.getUrl() != null) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting base tile url to " + type.getUrl() + " for map " + type.getId() + "');");
	                        }
	                        out.println("\t\t" + type.getId() + ".baseUrls = new Array();");
	                        out.println("\t\t" + type.getId() + ".baseUrls[0]=\"" + type.getUrl() + "?\";");
	                    }
	                    if (type.getLowResUrl() != null) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting lowres tile url to " + type.getLowResUrl() + " for map " + type.getId() + "');");
	                        }
	                        out.println("\t\t" + type.getId() + ".lowResBaseUrls = new Array();");
	                        out.println("\t\t" + type.getId() + ".lowResBaseUrls[0]=\"" + type.getLowResUrl() + "?\";");
	                    }
	                    if (type.getOverlayUrl() != null) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting overlay tile url to " + type.getOverlayUrl() + " for map " + type.getId() + "');");
	                        }
	                        out.println("\t\t" + type.getId() + ".overlayBaseUrls = new Array();");
	                        out.println("\t\t" + type.getId() + ".overlayBaseUrls[0]=\"" + type.getOverlayUrl() + "?\";");
	                    }
	                    if (type.getCopyright() != null) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting copyright for map " + type.getId() + "');");
	                        }
	                        out.println("\t\t" + type.getId() + ".getCopyright = function() {");
	                        out.println("\t\t\treturn '" + type.getCopyright() + "';");
	                        out.println("\t\t}");
	                    }
	                    if (type.getMaxZoom() >= 0) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting max zoom to " + type.getMaxZoom() + " for map " + type.getId() + "');");
	                        }
	                        out.println("\t\t" + type.getId() + ".getMaxZoomLevel = function() {");
	                        out.println("\t\t\treturn " + type.getMaxZoom() + ";");
	                        out.println("\t\t}");
	                    }
	                    if (type.getBaseType() != null) {
	                        String base = "G_NORMAL_MAP";
	                        if (type.getBaseType().equals("satellite"))
	                            base = "G_SATELLITE_MAP";
	                        else if (type.getBaseType().equals("hybrid"))
	                            base = "G_HYBRID_MAP";
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting alternative map type to " + base + " for map " + type.getId() + "');");
	                        }
	                        out.println("\t\t" + type.getId() + ".getAlternativeMapType = function() {");
	                        out.println("\t\t\treturn " + base + ";");
	                        out.println("\t\t}");
	                    }
	                    if (type.getLowerRightBound() != null && type.getUpperLeftBound() != null && points != null) {
	                        GoogleMapPointTag ul = (GoogleMapPointTag) points.get(type.getUpperLeftBound());
	                        GoogleMapPointTag lr = (GoogleMapPointTag) points.get(type.getLowerRightBound());
	                        if (ul != null && lr != null) {
	                            out.println("\t\t" + type.getId() + ".bounds = new GBounds(" + ul.getLongitude() + "," + ul.getLatitude() + "," + lr.getLongitude() + "," + lr.getLatitude() + ");");
	                            out.println("\t\t" + type.getId() + ".getBounds = function() {");
	                            out.println("\t\t\treturn this.bounds;");
	                            out.println("\t\t}");
	                        }
	                    }
	                    out.println("\t\t" + type.getId() + ".getLinkText = function() {");
	                    out.println("\t\t\treturn '" + type.getName() + "';");
	                    out.println("\t\t}");
	                    out.println("\t\t" + id + ".mapTypes[" + id + ".mapTypes.length] = " + type.getId() + ";");
	                    if (type.isShowOnStartup()) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting Google Map to initially display custom map " + type.getId() + "');");
	                        }
	                        out.println("\t\t" + id + ".setMapType(" + id + ".mapTypes[" + id + ".mapTypes.length-1]);");
	                    }
	                }
                }
                else if (version.indexOf("2") == 0) {
                    Enumeration names = mapTypes.keys();
	                while (names.hasMoreElements()) {
	                    int layerCount = -1;
	                    GoogleMapMapTypeTag type = (GoogleMapMapTypeTag) mapTypes.get(names.nextElement());
	                    if (debug && version.indexOf("2") == 0) {
                            out.println("\t\tGLog.write('Adding custom map " + type.getId() + "');");
                        }
	                    out.println("\t\tvar " + type.getId() + "_array = new Array();");
	                    String copy = type.getCopyright();
	                    int minZoom = type.getMinZoom();
	                    int maxZoom = type.getMaxZoom();
	                    if (minZoom < 0)
	                        minZoom = 0;
	                    if (maxZoom < 0) 
	                        maxZoom = 0;
	                    if (copy == null)
	                        copy = "";
	                    String base = "G_NORMAL_MAP";
	                    if (type.getBaseType() != null) {
	                        if (type.getBaseType().equals("satellite"))
	                            base = "G_SATELLITE_MAP";
	                        else if (type.getBaseType().equals("hybrid"))
	                            base = "G_HYBRID_TYPE";
	                    }
	                    if (type.getUrl() != null) {
	                        layerCount++;
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Adding base tile for custom map " + type.getId() + "');");
	                        }
	                        out.println("\t\tvar " + type.getId() + "_base = new GTileLayer(new GCopyrightCollection(\"" + copy + "\"), " + minZoom + ", " + maxZoom + ");");
	                        out.println("\t\t" + type.getId() + "_base.getCopyright = function(a, b) {");
	                        out.println("\t\t\treturn \"" + copy + "\";");
	                        out.println("\t\t}");
	                        out.println("\t\t" + type.getId() + "_base.getTileUrl = function(a, b) {");
	                        out.println("\t\tvar oldZoom = 17 - b;");
	                        out.println("\t\t\treturn \"" + type.getUrl() + "?x=\" + a.x + \"&y=\" + a.y + \"&zoom=\" + oldZoom;");
	                        out.println("\t\t}");
	                        out.println("\t\t" + type.getId() + "_base.isPng = function(a, b) {");
	                        out.println("\t\t\treturn " + type.isPng() + ";");
	                        out.println("\t\t}");
	                        out.println("\t\t" + type.getId() + "_array[" + layerCount + "] = " + type.getId() + "_base;");
	                    }
	                    if (type.getOverlayUrl() != null) {
	                        layerCount++;
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Adding overlay tile for map " + type.getId() + "');");
	                        }
	                        out.println("\t\tvar " + type.getId() + "_overlay = new GTileLayer(new GCopyrightCollection(\"" + copy + "\"), " + minZoom + ", " + maxZoom + ");");
	                        out.println("\t\t" + type.getId() + "_overlay.getCopyright = function(a, b) {");
	                        out.println("\t\t\treturn \"" + copy + "\";");
	                        out.println("\t\t}");
	                        out.println("\t\t" + type.getId() + "_overlay.getTileUrl = function(a, b) {");
	                        out.println("\t\tvar oldZoom = 17 - b;");
	                        out.println("\t\t\treturn \"" + type.getOverlayUrl() + "?x=\" + a.x + \"&y=\" + a.y + \"&zoom=\" + oldZoom;");
	                        out.println("\t\t}");
	                        out.println("\t\t" + type.getId() + "_overlay.isPng = function(a, b) {");
	                        out.println("\t\t\treturn " + type.isPng() + ";");
	                        out.println("\t\t}");
	                        out.println("\t\t" + type.getId() + "_array[" + layerCount + "] = " + type.getId() + "_overlay;");
	                    }
	                    out.println("\t\tvar " + type.getId() + " = new GMapType(" + type.getId() + "_array, " + base + ".getProjection(), \"" + type.getName() + "\", {shortName:\"" + type.getName() + "\",maxResolution:" + maxZoom + ",minResolution:" + minZoom + ",errorMessage:_mMapError});");
	                    out.println("\t\t" + id + ".addMapType(" + type.getId() + ");");
	                    if (type.isShowOnStartup()) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting Google Map to initially display custom map " + type.getId() + "');");
	                        }
	                        out.println("\t\t" + id + ".setMapType(" + type.getId() + ");");
	                    }
	                }
                }
            }
            if (version.indexOf("2") == 0) {
                out.println("\t\tsetZoomLevels();");
            }
            double lon = 0.00d;
            double lat = 0.00d;
            if (centerLongitude >= -180.00d && centerLatitude >= -180.00d) {
                lon = centerLongitude;
                lat = centerLatitude;
            }
            else { //calculate center point from points..
                lon = (largeLon + smallLon) / 2;
                lat = (largeLat + smallLat) / 2;
                centerLatitude = lat;
                centerLongitude = lon;
            }//end find centerpoint...
            if (bound && version.indexOf("2") == 0) {
                if (debug)
                    out.println("\t\tGLog.write('Creating bounding box for map.');");
                double adjustedSmallLon = smallLon - 0.05;
                double adjustedSmallLat = smallLat - 0.05;
                double adjustedLargeLon = largeLon + 0.05;
                double adjustedLargeLat = largeLat + 0.05;
                out.println("\t\tallowedBounds = new GLatLngBounds(new GLatLng(" + adjustedSmallLat + ", " + adjustedSmallLon + "), new GLatLng(" + adjustedLargeLat + ", " + adjustedLargeLon + "));");
                out.println("\t\tGEvent.addListener(" + id + ", 'move', function() {");
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Move event fired by map " + id + ".');");
                }
                out.println("\t\t\tcheckBounds();");
                out.println("\t\t});");
            }
            if (debug && version.indexOf("2") == 0) {
                out.println("\t\tGLog.write('Calculating default center and zoom values.');");
            }
            if (zoom < 0) {
                out.println("\t\t" + id + ".centerAndZoom(new GPoint(" + lon + ", " + lat + "), 8);");
            }
            else {
                out.println("\t\t" + id + ".centerAndZoom(new GPoint(" + lon + ", " + lat + "), " + zoom + ");");
            }
            //Render map labels if version 2...
            if (version.indexOf("2") == 0 && labels != null) {
                for (int i = 0; i < labels.size(); i++) {
                    GoogleMapLabelTag label = (GoogleMapLabelTag) labels.elementAt(i);
                    GoogleMapPointTag point = (GoogleMapPointTag) points.get(label.getPoint());
	                if (point != null) {
	                    if (debug && version.indexOf("2") == 0) {
	                        out.println("\t\tGLog.write('Adding label to map using point " + point.getId() + "');");
	                    }
	                    String constructor = "new GLatLng(" + point.getLatitude() + ", " + point.getLongitude() + "), ";
	                    constructor += "'";
	                    if (label.getStyle() != null) {
	                        constructor += "<div style=\"" + label.getStyle() + "\">";
	                    }
	                    constructor += label.getContent();
	                    if (label.getStyle() != null) {
	                        constructor += "</div>";
	                    }
	                    constructor += "', " + label.getOpacity() + ", ";
	                    if (label.getCss_class() != null) {
	                        constructor += "'" + label.getCss_class() + "'";
	                    }
	                    else {
	                        constructor += "null";
	                    }
	                    constructor += ", " + label.getX_offset() + ", " + label.getY_offset();
	                    out.println("\t\tvar label_" + i + " = new Label(" + constructor + ");");
	                    out.println("\t\t" + id + ".addOverlay(label_" + i + ");");
	                }
                }
            }
            //Renders inserts if version 2...
            if (version.indexOf("2") == 0 && inserts != null) {
                if (debug) {
                    out.println("\t\tGLog.write('Adding inserts to map with id " + id + "');");
                }
                for (int i = 0; i < inserts.size(); i++) {
                    GoogleMapInsertTag insert = (GoogleMapInsertTag) inserts.elementAt(i);
                    GoogleMapPointTag point = (GoogleMapPointTag) points.get(insert.getPoint());
	                if (point != null) {
	                    if (debug) {
	                        out.println("\t\tGLog.write('Adding insert " + insert.getId() + " to map using point " + point.getId() + "');");
	                    }  
	                    out.println("\t\t" + insert.getId() + " = new Insert(new GLatLng(" + point.getLatitude() + ", " + point.getLongitude() + "), \"" + insert.getUrl() + "\", new GSize(" + insert.getWidth() + ", " + insert.getHeight() + "), " + insert.getBaseZoom() + ");");
	                    out.println("\t\t" + id + ".addOverlay(" + insert.getId() + ");");
	                    out.print("\t\tif (");
	                    for (int j = 0; j < insert.getMapTypeCount(); j++) {
	                        String mapType = insert.getMapType(j);
	                        if (j > 0) {
	                            out.print(" || ");
	                        }
	                        out.print(id + ".getCurrentMapType().getName() == '" + mapType + "'");
	                    }
	                    out.println(") {");
	                    out.println("\t\t\t" + insert.getId() + ".show();");
	                    out.println("\t\t}");
	                    out.println("\t\telse {");
	                    out.println("\t\t\t" + insert.getId() + ".hide();");
	                    out.println("\t\t}");
	                }
	                else {
	                    if (debug)
	                        out.println("\t\tGLog.write('Point was null in " + insert.getId() + "');");
	                }
                }
            }
            //Render the markers...
            if (markers != null && markers.size() > 0) {
	            Enumeration names = markers.keys();
	            while (names.hasMoreElements()) {
	                GoogleMapMarkerTag marker = (GoogleMapMarkerTag) markers.get(names.nextElement());
	                GoogleMapPointTag point = (GoogleMapPointTag) points.get(marker.getPoint());
	                if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding marker " + marker.getId() + " using point " + point.getId() + "');");
                    }
	                if (point != null) {
	                    GoogleMapIconTag icon = marker.getIcon();
	                    if (icon != null) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Setting custom icon for marker " + marker.getId() + "');");
	                        }
	                        out.println("\t\tvar " + marker.getId() + "_icon = new GIcon();");
	                        out.println("\t\t" + marker.getId() + "_icon.image = \"" + icon.getIcon() + "\";");
	                        out.println("\t\t" + marker.getId() + "_icon.iconSize = new GSize(" + icon.getIconWidth() + ", " + icon.getIconHeight() + ");");
	                        if (icon.getShadow() != null) {
	                            out.println("\t\t" + marker.getId() + "_icon.shadow = \"" + icon.getShadow() + "\";");
	                            out.println("\t\t" + marker.getId() + "_icon.shadowSize = new GSize(" + icon.getShadowWidth() + ", " + icon.getShadowHeight() + ");");
	                        }
	                        out.println("\t\t" + marker.getId() + "_icon.iconAnchor = new GPoint(" + icon.getAnchorX() + ", " + icon.getAnchorY() + ");");
	                        out.println("\t\t" + marker.getId() + "_icon.infoWindowAnchor = new GPoint(" + icon.getInfoWindowAnchorX() + ", " + icon.getInfoWindowAnchorY() + ");");
	                        if (marker.isDraggable() && (version.compareTo("2.46") >= 0 || version.equals("2"))) {
	                            out.println("\t\tvar " + marker.getId() + " = new GMarker(new GLatLng(" + point.getLatitude() + ", " + point.getLongitude() + "), {icon: " + marker.getId() + "_icon, draggable: true});");  
	                        }
	                        else {
	                            out.println("\t\tvar " + marker.getId() + " = new GMarker(new GPoint(" + point.getLongitude() + ", " + point.getLatitude() + "), " + marker.getId() + "_icon);");
	                        }
	                    }
	                    else {
	                        if (marker.isDraggable() && (version.compareTo("2.46") >= 0 || version.equals("2"))) {
	                            out.println("\t\tvar " + marker.getId() + " = new GMarker(new GLatLng(" + point.getLatitude() + ", " + point.getLongitude() + "), {draggable: true});");
	                        }
	                        else {
	                            out.println("\t\tvar " + marker.getId() + " = new GMarker(new GPoint(" + point.getLongitude() + ", " + point.getLatitude() + "));");
	                        }
	                    }
	                    if (clusterer == null) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Adding marker " + marker.getId() + " to map " + id + "');");
	                        }
	                        out.println("\t\t" + id + ".addOverlay(" + marker.getId() + ");");
	                    }
	                    else {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Adding marker " + marker.getId() + " to clusterer " + id + "_cluster');");
	                        }
	                        out.println("\t\t" + id + "_cluster.AddMarker(" + marker.getId() + ", \"Zoom in for details\");");
	                    }
                        if (marker.isDraggable() && (version.compareTo("2.46") >= 0 || version.equals("2"))) {
                            out.println("\t\t" + marker.getId() + ".enableDragging();");
                        }
	                    if (marker.getInfoWindow() != null) {
	                        if (marker.getInfoWindow().isTabbed()) {
	                            GoogleMapInfoWindowTabbedTag info = (GoogleMapInfoWindowTabbedTag) marker.getInfoWindow();
	                            if (debug && version.indexOf("2") == 0) {
	                                out.println("\t\tGLog.write('Setting tabbed infowindow for marker " + marker.getId() + "');");
	                            }
	                            int tabWidth = 88 * info.getTabCount();
	                            String style = info.getStyle();
	                            if (style == null)
	                                style = "white-space: nowrap; width: " + tabWidth + "px;";
	                            String css_class = "";
	                            if (info.getCss_class() != null)
	                                css_class = "class=\\\"" + info.getCss_class() + "\\\"";
	                            out.println("\t\tvar " + marker.getId() + "_tabs = new Array();");
	                            for (int i = 0; i < info.getTabCount(); i++) {
	                                GoogleMapTabTag tab = info.getTab(i);
	                                out.println("\t\t" + marker.getId() + "_tabs.push(new GInfoWindowTab(\"" + tab.getLabel() + "\", \"<div " + css_class + " style=\\\"" + style + "\\\">" + tab.getContent() + "</div>\"));");
	                            }
	                            out.println("\t\tGEvent.addListener(" + marker.getId() + ", 'click', function() {");
	                            if (debug && version.indexOf("2") == 0) {
	                                out.println("\t\t\tGLog.write('Click event fired by marker " + marker.getId() + ".');");
	                            }
	                            out.println("\t\t\t" + marker.getId() + ".openInfoWindowTabsHtml(" + marker.getId() + "_tabs);");
	                            out.println("\t\t});");
	                            if (info.isDisplay()) {
		                            out.println("\t\t" + marker.getId() + ".openInfoWindowTabsHtml(" + marker.getId() + "_tabs);");
	                            }
	                        }
	                        else {
	                            if (debug && version.indexOf("2") == 0) {
	                                out.println("\t\tGLog.write('Setting info window for marker  " + marker.getId() + "');");
	                            }
	                            GoogleMapInfoWindowTag info = (GoogleMapInfoWindowTag) marker.getInfoWindow();
	                            String style = info.getStyle();
	                            if (style == null)
	                                style = "white-space: nowrap;";
	                            String css_class = "";
	                            if (info.getCss_class() != null)
	                                css_class = "class=\\\"" + info.getCss_class() + "\\\"";
		                        out.println("\t\tGEvent.addListener(" + marker.getId() + ", 'click', function() {");
		                        if (debug && version.indexOf("2") == 0) {
		                            out.println("\t\t\tGLog.write('Click event fired by marker " + marker.getId() + ".');");
		                        }
		                        out.println("\t\t\t" + marker.getId() + ".openInfoWindowHtml(\"<div " + css_class + " style=\\\"" + style + "\\\">" + info.getContent() + "</div>\");");
		                        out.println("\t\t});");
		                        if (info.isDisplay()) {
			                        out.println("\t\t" + marker.getId() + ".openInfoWindowHtml(\"<div " + css_class + " style=\\\"" + style + "\\\">" + info.getContent() + "</div>\");");
		                        }
	                        }
	                    }
	                    if (marker.getBlowup() != null) {
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\tGLog.write('Adding blowup map to marker " + marker.getId() + "');");
	                        }
	                        out.println("\t\tGEvent.addListener(" + marker.getId() + ", 'click', function() {");
	                        if (debug && version.indexOf("2") == 0) {
	                            out.println("\t\t\tGLog.write('Click event fired by marker " + marker.getId() + "');");
	                        }
	                        String parameters = "" + marker.getBlowup().getZoom();
	                        if (marker.getBlowup().getMaptype() != null) {
	                            if (marker.getBlowup().getMaptype().equalsIgnoreCase("satellite"))
	                                parameters += ", G_SATELLITE_MAP";
	                            else if (marker.getBlowup().getMaptype().equalsIgnoreCase("hybrid"))
	                                parameters += ", G_HYBRID_MAP";
	                            else
	                                parameters += ", G_NORMAL_MAP";
	                        }
	                        else {
	                            if (type.equalsIgnoreCase("hybrid")) {
	                                parameters += ", G_HYBRID_MAP";
	                            }
	                            else if (type.equalsIgnoreCase("satellite")) {
	                                parameters += ", G_SATELLITE_MAP";
	                            }
	                            else {
	                                parameters += ", G_NORMAL_MAP";
	                            }
	                        }
	                        out.println("\t\t\t" + marker.getId() + ".showMapBlowup(" + parameters + ");");
	                        out.println("\t\t});");
	                        if (marker.getBlowup().isDisplay()) {
		                        out.println("\t\t" + marker.getId() + ".showMapBlowup(" + parameters + ");");
	                        }
	                    }
	                    if (marker.getEvents() != null) {
	                        Vector e = marker.getEvents();
	                        for (int i = 0; i < e.size(); i++) {
	                            GoogleMapEventTag event = (GoogleMapEventTag) e.elementAt(i);
	                            String baseURL = event.getUrl();
	                            if (baseURL.indexOf("?") >= 0)
	                            	baseURL += "&";
	                            else
	                            	baseURL += "?";
	                            if (debug && version.indexOf("2") == 0) {
	                                out.println("\t\tGLog.write('Adding " + event.getAction() + " event to marker " +  marker.getId() + "');");
	                            }
	                            if (event.getAction().equals("click")) {
		                            out.println("\t\tGEvent.addListener(" + marker.getId() + ", '" + event.getAction() + "', function(overlay, point) {");
		                            if (debug && version.indexOf("2") == 0) {
		                                out.println("\t\t\tGLog.write('Click event fired by marker " + marker.getId() + "');");
		                            }
		                            if (event.isAsynchronous()) {
		                                out.println("\t\t\tvar asr = GXmlHttp.create();");
		                                out.println("\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + marker.getId() + "&type=marker\", true);");
		                                out.println("\t\t\tasr.send(null);");  
		                            }
		                            else {
		                                if (message != null) 
		                                    out.println("\t\t\tshowMessage();");
		                                out.println("\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + marker.getId() + "&type=marker\";");
		                            }
		                            out.println("\t\t});");
	                            }
	                            else if (event.getAction().indexOf("drag") >= 0 && (version.compareTo("2.46") >= 0 || version.equals("2"))) {
		                            out.println("\t\tGEvent.addListener(" + marker.getId() + ", '" + event.getAction() + "', function(overlay, point) {");
		                            if (debug && version.indexOf("2") == 0) {
		                                out.println("\t\t\tGLog.write('Drag event fired by marker " + marker.getId() + ".');");
		                            }
		                            out.println("\t\t\tvar longitude = " + marker.getId() + ".getPoint().x;");
		                            out.println("\t\t\tvar latitude = " + marker.getId() + ".getPoint().y;");
		                            if (event.isAsynchronous()) {
		                                out.println("\t\t\tvar asr = GXmlHttp.create();");
		                                out.println("\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + marker.getId() + "&type=marker&longitude=\" + longitude + \"&latitude=\" + latitude, true);");
		                                out.println("\t\t\tasr.send(null);");  
		                            }
		                            else {
		                                if (message != null) 
		                                    out.println("\t\t\tshowMessage();");
		                                out.println("\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + marker.getId() + "&type=marker&longitude=\" + longitude + \"&latitude=\" + latitude;");
		                            }
		                            out.println("\t\t});");
	                            }
	                            else if (event.getAction().equals("dblclick")) {
		                            out.println("\t\tGEvent.addListener(" + marker.getId() + ", 'mouseup', function(overlay, point) {");
		                            out.println("\t\t\tif (isDouble()) {");
		                            if (debug && version.indexOf("2") == 0) {
		                                out.println("\t\t\t\tGLog.write('Double click event fired by marker " + marker.getId() + "');");
		                            }
		                            if (event.isAsynchronous()) {
		                                out.println("\t\t\t\tvar asr = GXmlHttp.create();");
		                                out.println("\t\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + marker.getId() + "&type=marker\", true);");
		                                out.println("\t\t\t\tasr.send(null);");  
		                            }
		                            else {
		                                if (message != null) 
		                                    out.println("\t\t\t\tshowMessage();");
		                                out.println("\t\t\t\tdocument.location=\"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + marker.getId() + "&type=marker\";");
		                            }
		                            out.println("\t\t\t}");
		                            out.println("\t\t});"); 
	                            }
	                        }
	                    }
	                }
	            }
            }
            //add Controls...
            if (showZoomControl) {
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Adding zoom controls to map " + id + "');");
                }
                if (zoomControlSize == LARGE_ZOOM_CONTROL) {
                    out.println("\t\t" + id + ".addControl(new GLargeMapControl());");
                }
                else {
                    out.println("\t\t" + id + ".addControl(new GSmallMapControl());");
                }
            }
            if (showPanControl) {
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Adding pan controls to map " + id + "');");
                }
                out.println("\t\t" + id + ".enableDragging();");
            }
            else {
                out.println("\t\t" + id + ".disableDragging();");
            }
            if (showTypeControl) {
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Adding type controls to map " + id + "');");
                }
                out.println("\t\t" + id + ".addControl(new GMapTypeControl());");
            }
            if (showScaleControl) {
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Adding scale controls to map " + id + "');");
                }
                out.println("\t\t" + id + ".addControl(new GScaleControl());");
            }
            if (overviewControl != null && (version.compareTo("2.41") >= 0 || version.equals("2"))) {
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Adding overview control to map " + id + "');");
                }
                out.println("\t\t" + id + ".addControl(new GOverviewMapControl(new GSize(" + overviewControl.getWidth() + "," + overviewControl.getHeight() + ")));");
                if (overviewControl.wasPlaced()) {
                    out.println("\t\tsetTimeout(\"positionOverview(" + overviewControl.getX() + "," + overviewControl.getY() + ")\",1);");
                }
                else {
                    out.println("\t\tvar overview = document.getElementById(\"" + id + "_overview\");");
                    out.println("\t\tdocument.getElementById(\"" + id + "\").appendChild(overview);");
                }
            }
            if (headless && (version.compareTo("2.45") >= 0 || version.equals("2"))) {
                out.println("\t\t" + id + ".hideControls();");
                out.println("\t\tGEvent.addListener(" + id + ", 'mouseover', function() {");
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\t\tGLog.write('Mouseover event fired by map " + id + ".');");
                }
                out.println("\t\t\t" + id + ".showControls();");
                out.println("\t\t});");
                out.println("\t\tGEvent.addListener(" + id + ", 'mouseout', function() {");
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\t\tGLog.write('Mouseout event fired by map " + id + ".');");
                }
                out.println("\t\t\t" + id + ".hideControls();");
                out.println("\t\t});");
                
            }
            //Next add traffic markers...
            if (traffic_tags != null && traffic_tags.size() > 0) {
                Enumeration names = traffic_tags.keys();
                while (names.hasMoreElements()) {
                    GoogleMapTrafficTag events = (GoogleMapTrafficTag) traffic_tags.get(names.nextElement());
                    GoogleMapPointTag point = (GoogleMapPointTag) points.get(events.getPoint());
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Intializing traffic tag " + events.getId() + " using point " + point.getId() + "');");
                    }
                    if (events.geocode(point.getLongitude(), point.getLatitude())) {
                        for (int i = 0; i < events.eventCount(); i++) {
                            TrafficEventBean event = events.getEvent(i);
                            String event_id = events.getId() + "_" + i;
                            if (debug && version.indexOf("2") == 0) {
                                out.println("\t\tGLog.write('Adding traffic event " + events.getId() + "_" + i + " to traffic tag " + events.getId() + "');");
                            }
                            GoogleMapPointTag p = new GoogleMapPointTag();
                            p.setId(event_id);
                            p.setLatitude(event.getLatitude());
                            p.setLongitude(event.getLongitude());
                            addPoint(p);
                            GoogleMapIconTag icon = events.getIcon();
    	                    if (icon != null) {
    	                        if (debug && version.indexOf("2") == 0) {
                                    out.println("\t\tGLog.write('Setting custom icon for traffic event " + events.getId() + "');");
                                }
    	                        out.println("\t\tvar " + event_id + "_icon = new GIcon();");
    	                        out.println("\t\t" + event_id + "_icon.image = \"" + icon.getIcon() + "\";");
    	                        out.println("\t\t" + event_id + "_icon.iconSize = new GSize(" + icon.getIconWidth() + ", " + icon.getIconHeight() + ");");
    	                        if (icon.getShadow() != null) {
    	                            out.println("\t\t" + event_id + "_icon.shadow = \"" + icon.getShadow() + "\";");
    	                            out.println("\t\t" + event_id + "_icon.shadowSize = new GSize(" + icon.getShadowWidth() + ", " + icon.getShadowHeight() + ");");
    	                        }
    	                        out.println("\t\t" + event_id + "_icon.iconAnchor = new GPoint(" + icon.getAnchorX() + ", " + icon.getAnchorY() + ");");
    	                        out.println("\t\t" + event_id + "_icon.infoWindowAnchor = new GPoint(" + icon.getInfoWindowAnchorX() + ", " + icon.getInfoWindowAnchorY() + ");");
    		                    out.println("\t\tvar " + event_id + " = new GMarker(new GPoint(" + event.getLongitude() + ", " + event.getLatitude() + "), " + event_id + "_icon);");
    	                    }
    	                    else {
    	                        out.println("\t\tvar " + event_id + " = new GMarker(new GPoint(" + event.getLongitude() + ", " + event.getLatitude() + "));");
    	                    }
    	                    if (clusterer == null) {
    	                        if (debug && version.indexOf("2") == 0) {
                                    out.println("\t\tGLog.write('Adding traffic event " + events.getId() + "_" + i + " to clusterer " + id + "_cluster');");
                                }
    	                        out.println("\t\t" + id + ".addOverlay(" + event_id + ");");
    	                    }
    	                    else {
    	                        if (debug && version.indexOf("2") == 0) {
                                    out.println("\t\tGLog.write('Adding traffic event " + events.getId() + "_" + i + " to map " + id + "');");
                                }
    	                        out.println("\t\t" + id + "_cluster.AddMarker(" + event_id + ", \"" + event.getTitle() + "\");");
    	                    }
    	                    out.println("\t\tGEvent.addListener(" + event_id + ", 'click', function() {");
    	                    if (debug && version.indexOf("2") == 0) {
    	                        out.println("\t\t\tGLog.write('Click event fired by clustered marker " + event_id + ".');");
    	                    }
	                        out.println("\t\t\t" + event_id + ".openInfoWindowHtml(\"<div style=\\\"white-space:nowrap;\\\">" + event.getContent() + "</div>\");");
	                        out.println("\t\t});");
                        }
                    }
                    else {
                        System.err.println("Couldn't geocode, or none found.");
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\tGLog.write('Error geocoding traffic event in taffic tag " + events.getId() + "');");
                        }
                    }
                 }
             }
            //Now do polylines...
            if (polylines != null && polylines.size() > 0) {
                Enumeration names = polylines.keys();
                while (names.hasMoreElements()) {
                    GoogleMapPolylineTag line = (GoogleMapPolylineTag) polylines.get(names.nextElement());
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding polyline " + line.getId() + " to map " + id + "');");
                    }
                    out.print("\t\tvar " + line.getId() + " = new GPolyline([");
                    for (int p = 0; p < line.pointCount(); p++) {
                        GoogleMapPointTag point = (GoogleMapPointTag) points.get(line.getPoint(p));
                        if (point != null) {
                            out.print("new GPoint(" + point.getLongitude() + ", " + point.getLatitude() + ")");
                            if (p < line.pointCount() - 1)
                                out.print(", ");
                        }
                    }
                    out.println("], \"" + line.getColor() + "\", " + line.getWeight() + ", " + line.getOpacity() + ");");
                    out.println("\t\t" + id + ".addOverlay(" + line.getId() + ");");
                    if (line.getEvents() != null) {
                        Vector e = line.getEvents();
                        for (int j = 0; j < e.size(); j++) {
                            GoogleMapEventTag event = (GoogleMapEventTag) e.elementAt(j);
                            String baseURL = event.getUrl();
                            if (baseURL.indexOf("?") >= 0)
                            	baseURL += "&";
                            else
                            	baseURL += "?";
                            if (debug && version.indexOf("2") == 0) {
                                out.println("\t\tGLog.write('Adding " + event.getAction() + " event to polyline " + line.getId() + "');");
                            }
                            if (event.getAction().equals("click")) {
	                            out.println("\t\tGEvent.addListener(" + line.getId() + ", 'click', function(overlay, point) {");
	                            if (debug && version.indexOf("2") == 0) {
	                                out.println("\t\t\tGLog.write('Click event fired by polyline " + line.getId() + ".');");
	                            }
	                            if (event.isAsynchronous()) {
	                                out.println("\t\t\tvar asr = GXmlHttp.create();");
	                                out.println("\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + line.getId() + "&type=polyline\", true);");
	                                out.println("\t\t\tasr.send(null);");  
	                            }
	                            else {
	                                if (message != null) 
	                                    out.println("\t\t\t\tshowMessage();");
	                                out.println("\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + line.getId() + "&type=polyline\";");
	                            }
	                            out.println("\t\t});");
                            }
                            else if (event.getAction().equals("dblclick")) {
	                            out.println("\t\tGEvent.addListener(" + line.getId() + ", 'mouseup', function(overlay, point) {");
	                            out.println("\t\t\tif (isDouble()) {");
	                            if (debug && version.indexOf("2") == 0) {
	                                out.println("\t\t\t\tGLog.write('Double click event fired by line " + line.getId() + "');");
	                            }
	                            if (event.isAsynchronous()) {
	                                out.println("\t\t\t\tvar asr = GXmlHttp.create();");
	                                out.println("\t\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + line.getId() + "&type=polyline\", true);");
	                                out.println("\t\t\t\tasr.send(null);");  
	                            }
	                            else {
	                                if (message != null) 
	                                    out.println("\t\t\t\tshowMessage();");
	                                out.println("\t\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + line.getId() + "&type=polyline\";");
	                            }
	                            out.println("\t\t\t}");
	                            out.println("\t\t});"); 
                            }
                        }
                    }
                }
            }
            //Then circles...
            if (circles != null && circles.size() > 0) {
                Enumeration names = circles.keys();
                while(names.hasMoreElements()) {
                    GoogleMapCircleTag circle = (GoogleMapCircleTag) circles.get(names.nextElement());
                    GoogleMapPointTag point = (GoogleMapPointTag) points.get(circle.getPoint());
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding circle " + circle.getId() + " to map " + id + "');");
                    }
                    if (point != null) {
                        out.println("\t\tvar " + circle.getId() + " = drawCircle(" + point.getLongitude() + ", " + point.getLatitude() + ", " + circle.getRadius() + ", \"" + circle.getColor() + "\", " + circle.getWeight() + ", " + circle.getOpacity() + ");");
                        out.println("\t\t" + id + ".addOverlay(" + circle.getId() + ");");
                        if (circle.getEvents() != null) {
                            Vector e = circle.getEvents();
                            for (int j = 0; j < e.size(); j++) {
                                GoogleMapEventTag event = (GoogleMapEventTag) e.elementAt(j);
                                String baseURL = event.getUrl();
                                if (baseURL.indexOf("?") >= 0)
                                	baseURL += "&";
                                else
                                	baseURL += "?";
                                if (debug && version.indexOf("2") == 0) {
                                    out.println("\t\tGLog.write('Adding " + event.getAction() + " event to cricle " + circle.getId() + "');");
                                }
                                if (event.getAction().equals("click")) {
    	                            out.println("\t\tGEvent.addListener(" + circle.getId() + ", 'click', function(overlay, point) {");
    	                            if (debug && version.indexOf("2") == 0) {
    	                                out.println("\t\t\tGLog.write('Click event fired by circle " + circle.getId() + ".');");
    	                            }
    	                            if (event.isAsynchronous()) {
    	                                out.println("\t\t\tvar asr = GXmlHttp.create();");
    	                                out.println("\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + circle.getId() + "&type=circle\", true);");
    	                                out.println("\t\t\tasr.send(null);");  
    	                            }
    	                            else {
    	                                if (message != null) 
		                                    out.println("\t\t\t\tshowMessage();");
    	                                out.println("\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + circle.getId() + "&type=circle\";");
    	                            }
    	                            out.println("\t\t});");
                                }
                                else if (event.getAction().equals("dblclick")) {
    	                            out.println("\t\tGEvent.addListener(" + circle.getId() + ", 'mouseup', function(overlay, point) {");
    	                            out.println("\t\t\tif (isDouble()) {");
    	                            if (debug && version.indexOf("2") == 0) {
    	                                out.println("\t\t\t\tGLog.write('Double click event fired by circle " + circle.getId() + ".');");
    	                            }
    	                            if (event.isAsynchronous()) {
    	                                out.println("\t\t\t\tvar asr = GXmlHttp.create();");
    	                                out.println("\t\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + circle.getId() + "&type=circle\", true);");
    	                                out.println("\t\t\t\tasr.send(null);");  
    	                            }
    	                            else {
    	                                if (message != null) 
		                                    out.println("\t\t\t\tshowMessage();");
    	                                out.println("\t\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + circle.getId() + "&type=circle\";");
    	                            }
    	                            out.println("\t\t\t}");
    	                            out.println("\t\t});"); 
                                }
                            }
                        }
                    }
                }
            }
            //Then polygons...
            if (polygons != null && polygons.size() > 0) {
                Enumeration names = polygons.keys();
                while (names.hasMoreElements()) {
                    GoogleMapPolygonTag polygon = (GoogleMapPolygonTag) polygons.get(names.nextElement());
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding polygon " + polygon.getId() + " to map " + id + "');");
                    }
                    out.print("\t\tvar " + polygon.getId() + " = new GPolyline([");
                    for (int p = 0; p < polygon.pointCount(); p++) {
                        GoogleMapPointTag point = (GoogleMapPointTag) points.get(polygon.getPoint(p));
                        if (point != null) {
                            out.print("new GPoint(" + point.getLongitude() + ", " + point.getLatitude() + "), ");
                        }
                    }
                    GoogleMapPointTag point = (GoogleMapPointTag) points.get(polygon.getPoint(0));
                    out.print("new GPoint(" + point.getLongitude() + ", " + point.getLatitude() + ")");
                    out.println("], \"" + polygon.getColor() + "\", " + polygon.getWeight() + ", " + polygon.getOpacity() + ");");
                    out.println("\t\t" + id + ".addOverlay(" + polygon.getId() + ");");
                    if (polygon.getEvents() != null) {
                        Vector e = polygon.getEvents();
                        for (int j = 0; j < e.size(); j++) {
                            GoogleMapEventTag event = (GoogleMapEventTag) e.elementAt(j);
                            String baseURL = event.getUrl();
                            if (baseURL.indexOf("?") >= 0)
                            	baseURL += "&";
                            else
                            	baseURL += "?";
                            if (debug && version.indexOf("2") == 0) {
                                out.println("\t\tGLog.write('Adding " + event.getAction() + " to polygon " + polygon.getId() + "');");
                            }
                            if (event.getAction().equals("click")) {
	                            out.println("\t\tGEvent.addListener(" + polygon.getId() + ", 'click', function(overlay, point) {");
	                            if (debug && version.indexOf("2") == 0) {
	                                out.println("\t\t\tGLog.write('Click event fired by polygon " + polygon.getId() + ".');");
	                            }
	                            if (event.isAsynchronous()) {
	                                out.println("\t\t\tvar asr = GXmlHttp.create();");
	                                out.println("\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + polygon.getId() + "&type=polygon\", true);");
	                                out.println("\t\t\tasr.send(null);");  
	                            }
	                            else {
	                                if (message != null) 
	                                    out.println("\t\t\t\tshowMessage();");
	                                out.println("\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + polygon.getId() + "&type=polygon\";");
	                            }
	                            out.println("\t\t});");
                            }
                            else if (event.getAction().equals("dblclick")) {
	                            out.println("\t\tGEvent.addListener(" + polygon.getId() + ", 'mouseup', function(overlay, point) {");
	                            out.println("\t\t\tif (isDouble()) {");
	                            if (debug && version.indexOf("2") == 0) {
	                                out.println("\t\t\t\tGLog.write('Double click event fired by polygon " + polygon.getId() + ".');");
	                            }
	                            if (event.isAsynchronous()) {
	                                out.println("\t\t\t\tvar asr = GXmlHttp.create();");
	                                out.println("\t\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + polygon.getId() + "&type=polygon\", true);");
	                                out.println("\t\t\t\tasr.send(null);");  
	                            }
	                            else {
	                                if (message != null) 
	                                    out.println("\t\t\t\tshowMessage();");
	                                out.println("\t\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + polygon.getId() + "&type=polygon\";");
	                            }
	                            out.println("\t\t\t}");
	                            out.println("\t\t});"); 
                            }
                        }
                    }
                }
            }
            //And last boxes...
            if (boxes != null && boxes.size() > 0) {
                Enumeration names = boxes.keys();
                while (names.hasMoreElements()) {
                    GoogleMapBoxTag box = (GoogleMapBoxTag) boxes.get(names.nextElement());
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding box " + box.getId() + " to map " + id + "');");
                    }
                    if (box.pointCount() > 1) {
                        out.print("\t\tvar " + box.getId() + " = new GPolyline([");
                        GoogleMapPointTag ul = (GoogleMapPointTag) points.get(box.getPoint(0));
                        GoogleMapPointTag lr = (GoogleMapPointTag) points.get(box.getPoint(1));
                        out.print("new GPoint(" + ul.getLongitude() + ", " + ul.getLatitude() + "), ");
                        out.print("new GPoint(" + lr.getLongitude() + ", " + ul.getLatitude() + "), ");
                        out.print("new GPoint(" + lr.getLongitude() + ", " + lr.getLatitude() + "), ");
                        out.print("new GPoint(" + ul.getLongitude() + ", " + lr.getLatitude() + "), ");
                        out.print("new GPoint(" + ul.getLongitude() + ", " + ul.getLatitude() + ")");
                        out.println("], \"" + box.getColor() + "\", " + box.getWeight() + ", " + box.getOpacity() + ");");
                        out.println("\t\t" + id + ".addOverlay(" + box.getId() + ");");
                        if (box.getEvents() != null) {
                            Vector e = box.getEvents();
                            for (int j = 0; j < e.size(); j++) {
                                GoogleMapEventTag event = (GoogleMapEventTag) e.elementAt(j);
                                String baseURL = event.getUrl();
                                if (baseURL.indexOf("?") >= 0)
                                	baseURL += "&";
                                else
                                	baseURL += "?";
                                if (debug && version.indexOf("2") == 0) {
                                    out.println("\t\tGLog.write('Adding " + event.getAction() + " event to box " + box.getId() + "');");
                                }
                                if (event.getAction().equals("click")) {
    	                            out.println("\t\tGEvent.addListener(" + box.getId() + ", 'click', function(overlay, point) {");
    	                            if (debug && version.indexOf("2") == 0) {
    	                                out.println("\t\t\tGLog.write('Click event fired by box " + box.getId() + ".');");
    	                            }
    	                            if (event.isAsynchronous()) {
    	                                out.println("\t\t\tvar asr = GXmlHttp.create();");
    	                                out.println("\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + box.getId() + "&type=box\", true);");
    	                                out.println("\t\t\tasr.send(null);");  
    	                            }
    	                            else {
    	                                if (message != null) 
		                                    out.println("\t\t\t\tshowMessage();");
    	                                out.println("\t\t\tdocument.location=\""+ baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + box.getId() + "&type=box\";");
    	                            }
    	                            out.println("\t\t});");
                                }
                                else if (event.getAction().equals("dblclick")) {
    	                            out.println("\t\tGEvent.addListener(" + box.getId() + ", 'mouseup', function(overlay, point) {");
    	                            out.println("\t\t\tif (isDouble()) {");
    	                            if (debug && version.indexOf("2") == 0) {
    	                                out.println("\t\t\t\tGLog.write('Double click event fired by box " + box.getId() + ".');");
    	                            }
    	                            if (event.isAsynchronous()) {
    	                                out.println("\t\t\t\tvar asr = GXmlHttp.create();");
    	                                out.println("\t\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + box.getId() + "&type=box\", true);");
    	                                out.println("\t\t\t\tasr.send(null);");  
    	                            }
    	                            else {
    	                                if (message != null) 
		                                    out.println("\t\t\t\tshowMessage();");
    	                                out.println("\t\t\t\tdocument.location=\"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&component=" + box.getId() + "&type=box\";");
    	                            }
    	                            out.println("\t\t\t}");
    	                            out.println("\t\t});"); 
                                }
                            }
                        }
                    }
                }
            }
            //center and zoom...
            //first recalculate to see if there where any additions...
            if (centerLongitude >= -180.00d && centerLatitude >= -180.00d) {
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Recalculating center for map " + id + "');");
                }
                lon = centerLongitude;
                lat = centerLatitude;
            }
            else { //calculate center point from points..
                lon = (largeLon + smallLon) / 2;
                lat = (largeLat + smallLat) / 2;
                centerLatitude = lat;
                centerLongitude = lon;
            }//end find centerpoint...
            if (zoom < 0) { //calcuate zoom from points if not defined by the user...
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Recalculating zoom for map " + id + "');");
                }
                double adjustment = 0.50d;
                if (showZoomControl || showTypeControl)
                    adjustment = 1.00d;
                if (version.trim().indexOf("1") == 0) { //we're version 1.x...
                    out.println("\t\tvar zoom = " + id + ".spec.getLowestZoomLevel(new GPoint(" + lon + ", " + lat + "), new GSize(" + ((largeLon - smallLon) + adjustment) + ", " + ((largeLat - smallLat) + adjustment) + "), " + id + ".viewSize);");
                    out.println("\t\t" + id + ".centerAndZoom(new GPoint(" + lon + ", " + lat + "), zoom);");
                }
                else { //we'll assume version 2.x and also hope for forward compatibility...
                    out.println("\t\tvar bounds = new GLatLngBounds();");
                    Enumeration key = points.keys();
                    while (key.hasMoreElements()) {
                        GoogleMapPointTag point = (GoogleMapPointTag) points.get(key.nextElement());
                        out.println("\t\tbounds.extend(new GLatLng(" + point.getLatitude() + ", " + point.getLongitude() + "));");
                    }
                    out.println("\t\t" + id + ".setZoom(" + id + ".getBoundsZoomLevel(bounds));");
                    out.println("\t\tlastCenterLat = " + id + ".getCenterLatLng().y;");
                    out.println("\t\tlastCenterLon = " + id + ".getCenterLatLng().x;");
                }
            }
            //Register map events...
            if (events != null) {
                for (int i = 0; i < events.size(); i++) {
                    GoogleMapEventTag event = (GoogleMapEventTag) events.elementAt(i);
                    String baseURL = event.getUrl();
                    if (baseURL.indexOf("?") >= 0)
                    	baseURL += "&";
                    else
                    	baseURL += "?";
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding " + event.getAction() + " event to map " + id + "');");
                    }
                    if (event.getAction().equals("click")) {
                        out.println("\t\tGEvent.addListener(" + id + ", '" + event.getAction() + "', function(overlay, point) {");
                        out.println("\t\t\tif (!overlay && point) {");
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\t\t\tGLog.write('" + event.getAction() + " event fired by map " + id + ".');");
                        }
                        out.println("\t\t\t\tvar longitude = point.x;");
                        out.println("\t\t\t\tvar latitude = point.y;");
                        if (event.isAsynchronous()) {
                            out.println("\t\t\t\tvar asr = GXmlHttp.create();");
                            out.println("\t\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&longitude=\" + longitude + \"&latitude=\" + latitude, true);");
                            out.println("\t\t\t\tasr.send(null);");                            
                        }
                        else {
                            if (message != null)
                                out.println("\t\t\t\tshowMessage();");
                            out.println("\t\t\t\tdocument.location = \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&longitude=\" + longitude + \"&latitude=\" + latitude;");
                        }
                        out.println("\t\t\t}");
                        out.println("\t\t});");
                    }
                    else if (event.getAction().equals("dblclick")) {
                        out.println("\t\tGEvent.addListener(" + id + ", 'mousedown', function(overlay, point) {");
                        out.println("\t\t\tif (isDouble()) {");
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\t\t\tGLog.write('Double click event fired by map " + id + ".');");
                        }
                        out.println("\t\t\t\tvar longitude = point.x;");
                        out.println("\t\t\t\tvar latitude = point.y;");
                        if (event.isAsynchronous()) {
                            out.println("\t\t\t\tvar asr = GXmlHttp.create();");
                            out.println("\t\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&longitude=\" + longitude + \"&latitude=\" + latitude, true);");
                            out.println("\t\t\t\tasr.send(null);");                            
                        }
                        else {
                            if (message != null)
                                out.println("\t\t\t\tshowMessage();");
                            out.println("\t\t\t\tdocument.location = \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&longitude=\" + longitude + \"&latitude=\" + latitude;");
                        }
                        out.println("\t\t\t}");
                        out.println("\t\t});");
                    }
                    else if (event.getAction().equals("moveend")) {
                        out.println("\t\tGEvent.addListener(" + id + ", '" + event.getAction() + "', function() {");
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\t\tGLog.write('Moveend event fired by map " + id + ".');");
                        }
                        out.println("\t\t\tvar longitude = " + id + ".getCenterLatLng().x;");
                        out.println("\t\t\tvar latitude = " + id + ".getCenterLatLng().y;");
                        out.println("\t\t\tif (latitude != lastCenterLat || longitude != lastCenterLon) {");
                        out.println("\t\t\t\tlastCenterLat = latitude;");
                        out.println("\t\t\t\tlastCenterLon = longitude;");
                        if (event.isAsynchronous()) {
                            out.println("\t\t\t\tvar asr = GXmlHttp.create();");
                            out.println("\t\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&longitude=\" + longitude + \"&latitude=\" + latitude, true);");
                            out.println("\t\t\t\tasr.send(null);");
                        }
                        else {
                            if (message != null)
                                out.println("\t\t\t\tshowMessage();");
                        	out.println("\t\t\t\tdocument.location = \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&longitude=\" + longitude + \"&latitude=\" + latitude;");
                        }
                        out.println("\t\t\t}");
                        out.println("\t\t});");
                    }
                    else if (event.getAction().equals("zoom")) {
                        out.println("\t\tGEvent.addListener(" + id + ", '" + event.getAction() + "', function(oldzoom, newzoom) {");
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\t\tGLog.write('Zoom event fired by map " + id + ".');");
                        }
                        if (event.isAsynchronous()) {
                            out.println("\t\t\tvar asr = GXmlHttp.create();");
                            out.println("\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&zoom=\" + newzoom, true);");
                            out.println("\t\t\tasr.send(null);");
                        }
                        else {
                            if (message != null)
                                out.println("\t\t\tshowMessage();");
                        	out.println("\t\t\tdocument.location = \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&zoom=\" + newzoom;");
                        }
                        out.println("\t\t});");
                    }
                    else if (event.getAction().equals("maptypechanged")) {
                        out.println("\t\tGEvent.addListener(" + id + ", '" + event.getAction() + "', function() {");
                        out.println("\t\t\tvar type = " + id + ".getCurrentMapType();");
                        if (debug && version.indexOf("2") == 0) {
                            out.println("\t\t\tGLog.write('Maptypechanged event fired by map " + id + ".');");
                            out.println("\t\t\tGLog.write('Map type selected is: ' + type.getName());");
                        }
                        out.println("\t\t\tvar typeText = \"\";");
                        out.println("\t\t\tif (type == G_NORMAL_MAP) {");
                        out.println("\t\t\t\ttypeText = \"map\";");
                        out.println("\t\t\t}");
                        out.println("\t\t\telse if (type == G_HYBRID_MAP) {");
                        out.println("\t\t\t\ttypeText = \"hybrid\";");
                        out.println("\t\t\t}");
                        out.println("\t\t\tif (type == G_SATELLITE_MAP) {");
                        out.println("\t\t\t\ttypeText = \"satellite\";");
                        out.println("\t\t\t}");
                        if (event.isAsynchronous()) {
                            out.println("\t\t\tvar asr = GXmlHttp.create();");
                            out.println("\t\t\tasr.open(\"GET\", \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&type=\" + typeText, true);");
                            out.println("\t\t\tasr.send(null);");
                        }
                        else { 
                            if (message != null)
                                out.println("\t\t\tshowMessage();");
                        	out.println("\t\t\tdocument.location = \"" + baseURL + "event=" + event.getAction() + "&map=" + id + "&type=\" + typeText;");
                        }
                        out.println("\t\t});");
                    }
                }
            }
            if (coords != null && version.indexOf("2") == 0) {
                out.println("\t\tshowCoordinates(" + coords.getX() + ", " + coords.getY() + ");");
                out.println("\t\tGEvent.addListener(" + id + ", 'mousemove', function(point) {");
                out.println("\t\t\tupdateCoordinates(point.lng().toFixed(8), point.lat().toFixed(8));");
                out.println("\t\t});");
            }
            if (version.indexOf("2") == 0 && inserts != null) {
                out.println("\t\tGEvent.addListener(" + id + ", 'maptypechanged', function() {");
                out.println("\t\t\tvar _map;");
                out.println("\t\t\tvar mapType;");
                for (int i = 0; i < inserts.size(); i++) {
                    GoogleMapInsertTag insert = (GoogleMapInsertTag) inserts.elementAt(i);
                    if (insert.getMapTypeCount() > 0) {
	                    out.println("\t\t\t{");
	                    out.println("\t\t\t\t_map = " + insert.getId() + ".map_;");
	                    out.println("\t\t\t\tmapType = _map.getCurrentMapType().getName();");
	                    out.print("\t\t\t\tif (");
	                    for (int j = 0; j < insert.getMapTypeCount(); j++) {
	                        String mapType = insert.getMapType(j);
	                        if (j > 0) {
	                            out.print(" || ");
	                        }
	                        out.print("mapType == '" + mapType + "'");
	                    }
	                    out.println(") {");
	                    out.println("\t\t\t\t\t" + insert.getId() + ".show();");
	                    out.println("\t\t\t\t}");
	                    out.println("\t\t\t\telse {");
	                    out.println("\t\t\t\t\t" + insert.getId() + ".hide();");
	                    out.println("\t\t\t\t}");
	                    out.println("\t\t\t}");
                    }
                }       
                out.println("\t\t});");
            }
            if (message != null) {
                out.println("\t\thideMessage();");
            }
            if (overlays != null) {
                Enumeration names = overlays.keys();
                while (names.hasMoreElements()) {
                    GoogleMapImageOverlayTag image = (GoogleMapImageOverlayTag) overlays.get(names.nextElement());
                    if (debug && version.indexOf("2") == 0) {
                        out.println("\t\tGLog.write('Adding overlay image " + image.getId() + " to map " + id + "');");
                    }
                    out.println("\t\tshowImageOverlay(\"" + image.getId() + "\"," + image.getX() + "," + image.getY() + ");");
                }
            }
            //Now wrap it up...
            out.println("\t}");
            out.println("\tlastCenterLat = " + centerLatitude + ";");
            out.println("\tlastCenterLon = " + centerLongitude + ";");
            out.println("}");
            if (mouseWheelSupport  && version.indexOf("1") == 0) {
                if (debug && version.indexOf("2") == 0) {
                    out.println("\t\tGLog.write('Hooking mousewheel to map " + id + "');");
                }
                out.println("function exO(a){");
                out.println("\treturn Math.round(a)+\"px\"");
                out.println("}"); 
                out.println("function clamp(i, min, max) ");
                out.println("{");
                out.println("\tif (i <= min) ");
                out.println("\t\treturn min; ");
                out.println("\telse if (i >= max) ");
                out.println("\t\treturn max; ");
                out.println("\treturn i; ");
                out.println("");
                out.println("}");
                out.println("GMap.prototype.applyZoom = function(a) ");
                out.println("{");
                out.println("\tvar b = this; ");
                out.println("\tvar c = Math.floor(Math.log(b.viewSize.width) * Math.LOG2E - 2); ");
                out.println("\tvar d = b.zoomLevel - a; ");
                out.println("\tif (d > c) ");
                out.println("\t{");
                out.println("\t\td = c; ");
                out.println("\t}");
                out.println("\telse if (d < -c) ");
                out.println("\t{");
                out.println("\t\td = -c; ");
                out.println("\t}");
                out.println("\tvar e = Math.pow(2, d); ");
                out.println("\tb.div.style.zoom = e; ");
                out.println("\tvar f = b.viewSize.width * b.centerScreen.x; ");
                out.println("\tvar h = b.viewSize.height * b.centerScreen.y; ");
                out.println("\tb.div.style.left = exO((this._savedOffset.x - f) * e + f); ");
                out.println("\tb.div.style.top = exO((this._savedOffset.y - h) * e + h); ");
                out.println("}");
                out.println("function zoom(oEvent, scr) ");
                out.println("{");
                out.println("\tvar zoom_in = true; ");
                out.println("\tif (scr >= 120) ");
                out.println("\t\tzoom_in = false; ");
                out.println("\t" + id + ".smoothZoomTo(zoom_in); ");
                out.println("\tif (oEvent.preventDefault) ");
                out.println("\t\toEvent.preventDefault(); ");
                out.println("}");
                out.println("GMap.prototype.smoothZoomTo = function(zoom_in) ");
                out.println("{");
                out.println("\tvar a = this; ");
                out.println("\tif (!a._zoomInterval) ");
                out.println("\t\ta._targetZoom = a.getZoomLevel(); ");
                out.println("\ta._targetZoom = clamp(a._targetZoom + (zoom_in ? 1 : -1), 0, 17); ");
                out.println("\tif (a.div.style.zoom == undefined) ");
                out.println("\t{");
                out.println("\t\ta.zoomTo(a._targetZoom); ");
                out.println("\t\treturn; ");
                out.println("\t}");
                out.println("\tif (a._zoomInterval) ");
                out.println("\t\treturn; ");
                out.println("\ta._currentZoom = parseInt(a.getZoomLevel()); ");
                out.println("\ta._savedOffset={\"x\" : a.div.offsetLeft, \"y\" : a.div.offsetTop}; ");
                out.println("\ta.hideOverlays(); ");
                out.println("\tthis._zoomInterval = setInterval(function() { ");
                out.println("\t\ta._currentZoom += 0.3 * (a._targetZoom - a._currentZoom); ");
                out.println("\t\tif (Math.abs(a._targetZoom - a._currentZoom) < 0.05) ");
                out.println("\t\t{");
                out.println("\t\t\tif (a._savedOffset) ");
                out.println("\t\t\t{");
                out.println("\t\t\t\ta.div.style.left=exO(a._savedOffset.x); ");
                out.println("\t\t\t\ta.div.style.top=exO(a._savedOffset.y); ");
                out.println("\t\t\t}");
                out.println("\t\t\ta.div.style.zoom = 1; ");
                out.println("\t\t\ta.showOverlays(); ");
                out.println("\t\t\ta.zoomTo(a._targetZoom); ");
                out.println("\t\t\ta._savedOffset = null; ");
                out.println("\t\t\twindow.clearInterval(a._zoomInterval); ");
                out.println("\t\t\ta._zoomInterval = null; ");
                out.println("\t\t}");
                out.println("\t\telse ");
                out.println("\t\t{");
                out.println("\t\t\ta.applyZoom(a._currentZoom); ");
                out.println("\t\t}");
                out.println("\t}, 50); ");
                out.println("}");
                out.println("function hookMouseWheelHandlers(id) ");
                out.println("{");
                out.println("\tvar d = document.getElementById(id); ");
                out.println("\tif (d)");
                out.println("\t{");
                out.println("\t\ttry");
                out.println(" \t\t{");
                out.println("\t\t\tif (document.body.addEventListener) ");
                out.println("\t\t\t\td.addEventListener('DOMMouseScroll', function(oEvent) { "); 
                out.println("\t\t\t\tzoom(oEvent, oEvent.detail * -40); }, false); ");
                out.println("\t\t\telse ");
                out.println("\t\t\t\td.onmousewheel = function() {  ");
                out.println("\t\t\t\tzoom(event, event.wheelDelta);  ");
                out.println("\t\t\t\treturn false;  ");
                out.println("\t\t\t}");
                out.println("\t\t}catch (ex) {} ");
                out.println("\t}");
                out.println("}");
            }
            out.println("function drawCircle(lng, lat, radius, color, width, opacity) {");
            out.println("\tvar d2r = Math.PI/180;");
            out.println("\tvar r2d = 180/Math.PI; ");
            out.println("\tvar Clat = (radius/3963)*r2d;   ");
            out.println("\tvar Clng = Clat/Math.cos(lat*d2r); ");
            out.println("\tvar Cpoints = []; ");
            out.println("\tfor (var i=0; i < 33; i++) { ");
            out.println("\t\tvar theta = Math.PI * (i/16); ");
            out.println("\t\tCx = lng + (Clng * Math.cos(theta)); ");
            out.println("\t\tCy = lat + (Clat * Math.sin(theta)); ");
            out.println("\t\tvar P = new GPoint(Cx,Cy);");
            out.println("\t\tCpoints.push(P); ");
            out.println("\t}; ");
            out.println("\treturn new GPolyline(Cpoints, color, width, opacity);");
            out.println("}");
            out.println("//]]>");
            out.println("</script>");
        }
        catch(Exception ex) {
            ex.printStackTrace(System.err);
        }
    } 
    /**
     * Returns the list of GoogleMapBoxTags that have been added to this map.
     * 
     * 
     * @return A Hashtable that contains all the GoogleMapBoxTags in this map keyed by id.
     */
    public Hashtable getBoxes() {
        return boxes;
    }
    /**
     * Sets the GoogleMapBoxTag boxes to be rendered by this map.
     * 
     * @param boxes A Hashtable of GoogleMapBoxTags.
     */
    public void setBoxes(Hashtable boxes) {
        this.boxes = boxes;
    }
    /**
     * Returns the list of GoogleMapCircleTags that have been added to this map.
     * 
     * 
     * @return A Hashtable that contains all the GoogleMapCircleTags in this map keyed by id.
     */
    public Hashtable getCircles() {
        return circles;
    }
    /**
     * Returns the list of GoogleMapImageOverlayTags that have been added to this map.
     * 
     * @return A Hahtable that contains all the GoogleMapImageOverlayTags in this map, keyed by id.
     */
    public Hashtable getImageOverlays() {
        return overlays;
    }
    /**
     * Sets the GoogleMapCircleTags to be rendered by this map.
     * 
     * @param circles A Hashtable of GoogleMapCircleTags keyed by id.
     */
    public void setCircles(Hashtable circles) {
        this.circles = circles;
    }
    /**
     * Sets the GoogleMapImageOverlayTags to be rendered by this map.
     * 
     * @param images A Hahtable of GoogleMapImageOverlayTags keyed by id.
     */
    public void setImageOverlays(Hashtable images) {
        this.overlays = images;
    }
    /**
     * Returns the list of GoogleMapKeyTags that have been added to this map.
     * 
     * 
     * @return A Hashtable that contains all the GoogleMapKeysTags in this map keyed by domain name.
     */
    public Hashtable getKeys() {
        return keys;
    }
    /**
     * Sets the list of GoogleMapKeyTags for this map.
     * 
     * @param keys A Hashtable of GoogleMapKeyTags keyed by domain name.
     */
    public void setKeys(Hashtable keys) {
        this.keys = keys;
    }
    /**
     * Returns the largest latitude (in decimal form) of all points stored in this map.
     * 
     * @return The largest latitude of all points.
     */
    public double getLargeLat() {
        return largeLat;
    }
    /**
     * Sets the largest latitude (in decimal form) for this map. This is typically set
     * automatically when points are added. Developers should not override this method.
     */
    public void setLargeLat(double largeLat) {
        this.largeLat = largeLat;
    }
    /**
     * Returns the largest longitude (in decimal form) of all points located within
     * this map.
     * 
     * @return The largest longitude in this map.
     */
    public double getLargeLon() {
        return largeLon;
    }
    /**
     * Sets the largest longitude (in decimal form) for this map. This is typically set
     * automatically when points are added. Developers should not override this method.
     */
    public void setLargeLon(double largeLon) {
        this.largeLon = largeLon;
    }
    /**
     * Returns a list of all GoogleMapMarkerTags added to this map, keyed on their
     * ids.
     * 
     * @return A Hashtable of GoogleMapMarkerTags.
     */
    public Hashtable getMarkers() {
        return markers;
    }
    /**
     * Sets the list of the GoogleMapMarkerTags to be rendered by this map.
     * 
     * @param markers A Hashtable of GoogleMapMarkerTags keyed on their ids.
     */
    public void setMarkers(Hashtable markers) {
        this.markers = markers;
    }
    /**
     * Denotes whether or not pan control is enabled. If true then users
     * can pan the map, if false, they cannot.
     * 
     * @return True if pan enabled, false if not.
     */
    public boolean isPanEnabled() {
        return panEnabled;
    }
    /**
     * Sets whether or not users should be able to pan the map.
     * 
     * @param panEnabled True or false.
     */
    public void setPanEnabled(boolean panEnabled) {
        this.panEnabled = panEnabled;
    }
    /**
     * Returns a list of all the GoogleMapPointTags added to this map.
     * 
     * @return A Hashtable of GoogleMapPointTags keyed on their ids.
     */
    public Hashtable getPoints() {
        return points;
    }
    /**
     * Sets the list of GoogleMapPointTags to be used by overlays in this
     * map.
     * 
     * @param points A Hashtable of GoogleMapPointTags keyed on their ids.
     */
    public void setPoints(Hashtable points) {
        this.points = points;
    }
    /**
     * Returns a list of all the GoogleMapPolygonTags to be rendered by this map.
     * 
     * @return A Hashtable of GoogleMapPolygonTags keyed by id.
     */
    public Hashtable getPolygons() {
        return polygons;
    }
    /**
     * Sets the list of GoogleMapPolygonTags to be rendered by this map.
     * 
     * @param polygons A Hashtable of GoogleMapPolygonTags keyed by id.
     */
    public void setPolygons(Hashtable polygons) {
        this.polygons = polygons;
    }
    /**
     * Returns a list of all the GoogleMapMapTypeTags to be rendered by this map.
     * 
     * @return A Hashtable of GoogleMapMapTypeTags keyed by id.
     */
    public Hashtable getMapTypes() {
        return mapTypes;
    }
    /**
     * Sets the list of GoogleMapMapTypeTags to be rendered by this map.
     * 
     * @param mapTypes A Hashtable of GoogleMapMapTypeTags keyed by id.
     */
    public void setMapTypes(Hashtable mapTypes) {
        this.mapTypes = mapTypes;
    }
    /**
     * Returns a list of all the GoogleMapPolylineTags to be rendered by this map.
     * 
     * @return A Hashtable of GoogleMapPolylineTags keyed by id.
     */
    public Hashtable getPolylines() {
        return polylines;
    }
    /**
     * Sets the list of GoogleMapPolylineTags to be rendered by this map.
     * 
     * @param polylines A Hashtable of GoogleMapPolylineTags keyed by id.
     */
    public void setPolylines(Hashtable polylines) {
        this.polylines = polylines;
    }
    /**
     * Denotes whether or not this map displays a scale.
     * 
     * @return True if the scale is visible, false if not.
     */
    public boolean isShowScaleControl() {
        return showScaleControl;
    }
    /**
     * Sets whether or not this map should display a scale control.
     * 
     * @param showScaleControl True to show scale, false if not.
     */
    public void setShowScaleControl(boolean showScaleControl) {
        this.showScaleControl = showScaleControl;
    }
    /**
     * Returns the smalles latitude (in decimal form) of all points in this map.
     * 
     * @return The small latitude in this map.
     */
    public double getSmallLat() {
        return smallLat;
    }
    /**
     * Sets the smallest latitude (in decimal form) of all points in this map. This
     * is set automatically as points are added to the map. Developers should not
     * override this method.
     * 
     * @param smallLat The smallest latitude in this map.
     */
    public void setSmallLat(double smallLat) {
        this.smallLat = smallLat;
    }
    /**
     * Returns the smalles longitude (in decimal form) of all points in this map.
     * 
     * @return The small longitude in this map.
     */
    public double getSmallLon() {
        return smallLon;
    }
    /**
     * Sets the smallest longitude (in decimal form) of all points in this map. This
     * is set automatically as points are added to the map. Developers should not
     * override this method.
     * 
     * @param smallLon The smallest longitude in this map.
     */
    public void setSmallLon(double smallLon) {
        this.smallLon = smallLon;
    }
    /**
     * Returns the zoom control size for this map. Equals either
     * SMALL_ZOOM_CONTROL or LARGE_ZOOM_CONTROL.
     * 
     * @return The zoom control size for this map.
     */
    public int getZoomControlSize() {
        return zoomControlSize;
    }
    /**
     * Sets the zoom control size. This should equal either
     * SMALL_ZOOM_CONTROL or LARGE_ZOOM_CONTROL. If set to
     * SMALL_ZOOM_CONTROL, then only zoom in (+) and zoom out (-)
     * buttons are shown. If set to LARGE_ZOOM_CONTROL then a slider
     * is presented as well.
     * 
     * @param zoomControlSize The desired zoom control size.
     */
    public void setZoomControlSize(int zoomControlSize) {
        this.zoomControlSize = zoomControlSize;
    }
    /**
     * Returns the map's body contents.
     * 
     * @return The current body contents.
     */
    public String getBody() {
        return body;
    }
    /**
     * Returns the latitude (in decimal form) of the map's current centerpoint.
     * 
     * @return The current centerpoint latitude.
     */
    public double getCenterLatitude() {
        return centerLatitude;
    }
    /**
     * Returns the longitude (in decimal form) of the map's current centerpoint.
     * 
     * @return The current centerpoint longitude.
     */
    public double getCenterLongitude() {
        return centerLongitude;
    }
    /**
     * Returns the height of this map in pixels.
     * 
     * @return The map height in pixels.
     */
    public String getHeight() {
        return height;
    }
    /**
     * Denotes whether or not this map supports mouseWheel zoom control.
     * 
     * @return True if this map supports mousewheel control, false if not.
     */
    public boolean isMouseWheelSupport() {
        return mouseWheelSupport;
    }
    /**
     * Returns the scope of this map ("site" | "page").
     * 
     * @return The map scope.
     */
    public String getScope() {
        return scope;
    }
    /**
     * Denotes whether or not this map shows pan controls.
     * 
     * @return True if pan controls are shown, false if not.
     */
    public boolean isShowPanControl() {
        return showPanControl;
    }
    /**
     * Denotes whether or not this map shows type controls.
     * 
     * @return True if type controls are shown, false if not.
     */
    public boolean isShowTypeControl() {
        return showTypeControl;
    }
    /**
     * Denotes whether ot not this map shows zoom controls.
     * 
     * @return True if zoom controls are shown, false if not.
     */
    public boolean isShowZoomControl() {
        return showZoomControl;
    }
    /**
     * Returns the current map type (map | satellite | hybrid).
     * 
     * @return The current map type.
     */
    public String getType() {
        return type;
    }
    /**
     * Returns the version of the Google Maps API used by this map.
     * 
     * @return Google Maps API version.
     */
    public String getVersion() {
        return version;
    }
    /**
     * Returns the width of this map in pixels.
     * 
     * @return The width of the map in pixels.
     */
    public String getWidth() {
        return width;
    }
    /**
     * Returns the current zoom level of this map.
     * 
     * @return The current zoom level.
     */
    public int getZoom() {
        return zoom;
    }
    /**
     * Returns the list of all GoogleMapEventTags supported by this
     * map.
     * 
     * @return A Vector of GoogleMapEventTags.
     */
    public Vector getEvents() {
        return events;
    }
    /**
     * Sets the list of GoogleMapEventTags supported by this map.
     * 
     * @param events A Vector of GoogleMapEventTags.
     */
    public void setEvents(Vector events) {
        this.events = events;
    }
    /**
     * Returns the id of this map.
     * 
     * @return The id of this map.
     */
    public String getId() {
        return id;
    }
    /**
     * Returns the current message tag, or null if not defined.
     * 
     * @return A valid GoogleMapMessageTag
     */
    public GoogleMapMessageTag getMessage() {
        return message;
    }
    /**
     * Sets the message tag to display when loading or when actions are fired.
     * 
     * @param message A valid GoogleMapMessageTag
     */
    public void setMessage(GoogleMapMessageTag message) {
        this.message = message;
    }
    /**
     * Returns the URL to the XML file or generator that is to provide map data for points,
     * overlays and events for this map.
     * 
     * @return URL to an XML file or generator.
     */
    public String getXml() {
        return xml;
    }
    /**
     * Sets the URL for the XML file or generator that is to provide map data for points,
     * overlays and events for this map.
     * 
     * @param xml A valid URL to an XML file or generator that validates against the public DTD http://www.lamatek.com/GoogleMaps/dtds/googlemaps.dtd
     */
    public void setXml(String xml) {
        this.xml = xml;
    }
    /**
     * Returns the currently defined GoogleMapOverviewTag defined for this map.
     * 
     * @return A GoogleMapOverviewTag or null if none defined.
     */
    public GoogleMapOverviewTag getOverviewControl() {
        return overviewControl;
    }
    /**
     * Sets the GoogleMapOverviewTag to use for this map.
     * 
     * @param overviewControl an initialized GoogleMapOverviewTag
     */
    public void setOverviewControl(GoogleMapOverviewTag overviewControl) {
        this.overviewControl = overviewControl;
    }
    /**
     * Returns the current clusterer tag, or null if not defined.
     * 
     * @return A valid GoogleMapClusterTag
     */
    public GoogleMapClusterTag getClusterer() {
        return clusterer;
    }
    /**
     * Sets the cluster tag to used to cluster markers.
     * 
     * @param clusterer A valid GoogleMapClusterTag
     */
    public void setClusterer(GoogleMapClusterTag clusterer) {
        this.clusterer = clusterer;
    }
    /**
     * Adds a wms tag to this map.
     * 
     * @param tag An initialized GoogleMapWMSTag
     */
    public void addWMSTag(GoogleMapWMSTag tag) {
        if (wms == null)
            wms = new Hashtable();
        wms.put(tag.getId(), tag);
    }
    /**
     * Returns a GoogleMapWMSTag with the given id, or null
     * if a tag with that id is not present.
     * 
     * @return A GoogleMapWMSTag or null.
     */
    public GoogleMapWMSTag getWms(String id) {
        if (wms == null)
            return null;
        else
            return (GoogleMapWMSTag) wms.get(id);
    }
    /**
     * Returns a Hashtable of GoogleMapWMSTags, keyed by id, or null
     * if none exist in this map.
     * 
     * @return A Hashtable of GoogleMapWMSTags, keyed by id.
     */
    public Hashtable getWmsTypes() {
        return wms;
    }
    /**
     * Denotes whether or not debugging is turned on for this map. Only valid
     * on version 2 maps. Version 1 maps return false.
     * 
     * @return The debugging status of this map.
     */
    public boolean isDebug() {
        return debug;
    }
    /**
     * Turns debugging on or off for this map. If turned on, version 2 maps will
     * display a small pop-up window with debugging information in it.
     * 
     * @param debug True to turn on debugging, false to turn it off.
     * 
     */
    public void setDebug(boolean debug) {
        if (version != null && version.indexOf("2") == 0)
            this.debug = debug;
        else
            this.debug = false;
    }
    /**
     * Adds a label to this map.
     * 
     * @param label An initialized GoogleMapLabelTag
     */
    public void addLabel(GoogleMapLabelTag label) {
        if (labels == null)
            labels = new Vector();
        labels.addElement(label);
    }
    /**
     * Removes aa label from the map. 
     * 
     * @param label A label to remove from the map.
     */
    public void deleteLabel(GoogleMapLabelTag label) {
        if (labels != null)
            labels.remove(label);
    }
    /**
     * Sets the list of labels to display on the map.
     * 
     * @param labels A Vector containing GoogleMapLabelTag objects.
     */
    public void setLabels(Vector labels) {
        this.labels = labels;
    }
    /**
     * Returns the list of map labels in a Vector.
     * 
     * @return A Vector of GoogleMapLabelTag objects.
     */
    public Vector getLabels() {
        return labels;
    }
    /**
     * Denotes whether or not this map is in headless mode. Headless mode
     * hides user controls unless the cursor is inside the map.
     * 
     * @return True or false.
     */
    public boolean isHeadless() {
        return headless;
    }
    /**
     * Sets headless mode for this map. Headless mode will only display user
     * controls when the cursor is inside the map. Default is false (headless mode off).
     * 
     * @param headless True or false.
     */
    public void setHeadless(boolean headless) {
        this.headless = headless;
    }
    /**
     * Returns the maximum allowable zoom level for this map. Users will not be able to zoom
     * in higher than this number. Default is 17 (all the way in).
     * 
     * @return Maximum zoom level as an int.
     */
    public int getMaxZoom() {
        return maxZoom;
    }
    /**
     * Sets the maximum allowable zoom level for this map. Users will not be able to zoom
     * in higher than this number. Default is 17 (all the way in).
     * 
     * @param maxZoom zoom level as an int.
     */
    public void setMaxZoom(int maxZoom) {
        this.maxZoom = maxZoom;
    }
    /**
     * Returns the minimum allowable zoom level for this map. Users will not be able to zoom
     * out further than this number. Default is 0 (all the way out).
     * 
     * @return Minimum zoom level as an int.
     */
    public int getMinZoom() {
        return minZoom;
    }
    /**
     * Sets the minimum allowable zoom level for this map. Users will not be able to zoom
     * out further than this number. Default is 0 (all the way out).
     * 
     * @param minZoom zoom level as an int.
     */
    public void setMinZoom(int minZoom) {
        this.minZoom = minZoom;
    }
    /**
     * Returns whether or not this map is bound to it's contents. If bound, the map cannot
     * be panned outside the defined points. Default is false.
     * 
     * @return True or false denoting if this map is bound.
     */
    public boolean isBound() {
        return bound;
    }
    /**
     * Sets the bound state of this map. If bound, it cannot be panned outside the points that
     * have been defined in it (with a little fudge factor for smoother scrolling. Default is
     * false.
     * 
     * @param bound Sets the bound state of this map.
     */
    public void setBound(boolean bound) {
        this.bound = bound;
    }
    /**
     * Removes an insert from the map. 
     * 
     * @param insert An insert to remove from the map.
     */
    public void deleteInsert(GoogleMapInsertTag insert) {
        if (inserts != null)
            inserts.remove(insert);
    }
    /**
     * Adds an insert to this map.
     * 
     * @param insert An initialized GoogleMapInsertTag
     */
    public void addInsert(GoogleMapInsertTag insert) {
        if (inserts == null)
            inserts = new Vector();
        inserts.addElement(insert);
    }
    /**
     * Sets the list of inserts to display on the map.
     * 
     * @param inserts A Vector containing GoogleMapInsertTag objects.
     */
    public void setInserts(Vector inserts) {
        this.inserts = inserts;
    }
    /**
     * Returns the list of map inserts in a Vector.
     * 
     * @return A Vector of GoogleMapInsertTag objects.
     */
    public Vector getInserts() {
        return inserts;
    }
    /**
     * Adds a GoogleMapCoordinatesTag to the map.
     * 
     * @param coords An initialized GoogleMapCoordinates Tag.
     */
    public void addCoordinates(GoogleMapCoordinatesTag coords) {
        this.coords = coords;
    }
    /**
     * Returns the currently designated default language.
     * 
     * @return The 2 -digit language code.
     */
	public String getLanguage() {
		return language;
	}
	/**
	 * Sets the desired default 2-digit language code.
	 *  
	 * @param language The 2-figit language code to use.
	 */
	public void setLanguage(String language) {
		this.language = language;
	}
	/**
	 * Denotes whether or not the map is set to display current day and nighttime light
	 * conditions.
	 * 
	 * @return True or false.
	 */
	public boolean isShowDaylight() {
		return showDaylight;
	}
	/**
	 * Allows the map to display where the current day/night conditions are. Set to true
	 * to see light/dark, false if not. Default is false.
	 * 
	 * @param showDaylight true to show, false if not. 
	 */
	public void setShowDaylight(boolean showDaylight) {
		this.showDaylight = showDaylight;
	}
}
